﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Numerics;
using System.Text;
using ParserGenerator.Collections;
using ParserGenerator.Exceptions;
using ParserGenerator.Extensions;
using ParserGenerator.GrammarConstruction;
using ParserGenerator.Input;
using CSharp = ParserGenerator.Languages.CSharp;

namespace ParserGenerator.SyntacticAnalysis
{
    [Serializable]
    public class ProgramDescriptionTranslator
        : IExpressionTranslator
        , ITypeExpressionTranslator
        , IStatementTranslator
        , ITypeDeclaratorTranslator
        , IInterfaceMemberDeclaratorTranslator
        , IClassMemberDeclaratorTranslator
    {
        #region tokens
        public virtual CSharp.Expression TranslateBooleanLiteral(bool value)
        {
            return CSharp.Expression.NewLiteral(CSharp.Literal.NewBoolean(value));
        }

        public virtual CSharp.Expression TranslateIntegerLiteral(BigInteger value, SourceContext context)
        {
            if (int.MinValue <= value && value <= int.MaxValue)
                return CSharp.Expression.NewLiteral(CSharp.Literal.NewInteger(value));
            else if (uint.MinValue <= value && value <= uint.MaxValue)
                return CSharp.Expression.NewLiteral(CSharp.Literal.NewInteger(value, false, CSharp.IntegerTypeSuffix.U));
            else if (long.MinValue <= value && value <= long.MaxValue)
                return CSharp.Expression.NewLiteral(CSharp.Literal.NewInteger(value, false, CSharp.IntegerTypeSuffix.L));
            else if (ulong.MinValue <= value && value <= ulong.MaxValue)
                return CSharp.Expression.NewLiteral(CSharp.Literal.NewInteger(value, false, CSharp.IntegerTypeSuffix.UL));
            else
            {
                CSharp.Identifier global = CSharp.Identifier.New("global");
                CSharp.Identifier system = CSharp.Identifier.New("System");
                CSharp.Identifier numerics = CSharp.Identifier.New("Numerics");
                CSharp.Identifier bigInteger = CSharp.Identifier.New("BigInteger");
                CSharp.Identifier parse = CSharp.Identifier.New("Parse");
                CSharp.Expression str = TranslateStringLiteral(value.ToString());
                CSharp.Argument argStr = CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(str));
                CSharp.ArgumentList args = CSharp.ArgumentList.New(Sequence.Create(argStr));
                CSharp.QualifiedAliasMember globalSystem = CSharp.QualifiedAliasMember.New(global, system);
                CSharp.Expression globalSystemNumerics = CSharp.Expression.NewQualifiedAliasMemberAccess(globalSystem, numerics);
                CSharp.Expression globalSystemNumericsBigInteger = CSharp.Expression.NewObjectMemberAccess(globalSystemNumerics, bigInteger);
                CSharp.Expression bigIntegerParse = CSharp.Expression.NewObjectMemberAccess(globalSystemNumericsBigInteger, parse);
                CSharp.Expression call = CSharp.Expression.NewInvocation(bigIntegerParse, args);
                return call;
            }
        }

        public virtual CSharp.Expression TranslateFloatLiteral(double value)
        {
            if (double.IsPositiveInfinity(value))
                return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewDouble(), CSharp.Identifier.New("PositiveInfinity"));
            else if (double.IsNegativeInfinity(value))
                return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewDouble(), CSharp.Identifier.New("NegativeInfinity"));
            else if (double.IsNaN(value))
                return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewDouble(), CSharp.Identifier.New("NaN"));
            else
                return CSharp.Expression.NewLiteral(CSharp.Literal.NewDouble(value));
        }

        public virtual CSharp.Expression TranslateComplexLiteral(Complex value)
        {
            CSharp.Expression re = TranslateFloatLiteral(value.Real);
            CSharp.Expression im = TranslateFloatLiteral(value.Imaginary);
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier numerics = CSharp.Identifier.New("Numerics");
            CSharp.Identifier complex = CSharp.Identifier.New("Complex");
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemNumerics = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, numerics);
            CSharp.NamespaceOrTypeName globalSystemNumericsComplex = CSharp.NamespaceOrTypeName.NewQualified(globalSystemNumerics, complex);
            CSharp.TypeName complexTypeName = CSharp.TypeName.New(globalSystemNumericsComplex);
            CSharp.Type complexType = CSharp.Type.NewNamedStruct(complexTypeName);
            CSharp.Argument argRe = CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(re));
            CSharp.Argument argIm = CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(im));
            CSharp.ArgumentList args = CSharp.ArgumentList.New(Sequence.Create(argRe, argIm));
            return CSharp.Expression.NewObjectCreation(complexType, args);
        }

        public virtual CSharp.Expression TranslateCharLiteral(char c)
        {
            return CSharp.Expression.NewLiteral(CSharp.Literal.NewCharacter(c));
        }

        public virtual CSharp.Expression TranslateStringLiteral(string value)
        {
            if (value == null)
                throw new ArgumentNullException(nameof(value));
            return CSharp.Expression.NewLiteral(CSharp.Literal.NewString(value));
        }

        public virtual CSharp.Expression TranslateQuoteLiteral(string value)
        {
            if (value == null)
                throw new ArgumentNullException(nameof(value));
            if (value.Length == 1)
            {
                int[] codepoints = StringExtensions.GetCodepoints(value);
                if (codepoints.Length == 1 && 0 <= codepoints[0] && codepoints[0] <= 0xFFFF)
                    return TranslateCharLiteral((char)codepoints[0]);
            }
            return TranslateStringLiteral(value);
        }

        public virtual CSharp.Expression TranslateByteStringLiteral(ReadOnlyCollection<byte> value)
        {
            if (value == null)
                throw new ArgumentNullException(nameof(value));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier objectModel = CSharp.Identifier.New("ObjectModel");
            CSharp.Identifier readOnlyCollection = CSharp.Identifier.New("ReadOnlyCollection");
            CSharp.TypeArgumentList typeArgs = CSharp.TypeArgumentList.New(CSharp.TypeArguments.New(Sequence.Create(CSharp.TypeArgument.New(CSharp.Type.NewByte()))));
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemCollections = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, collections);
            CSharp.NamespaceOrTypeName globalSystemCollectionsObjectModel = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollections, objectModel);
            CSharp.NamespaceOrTypeName globalSystemCollectionsObjectModelReadOnlyCollection = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollectionsObjectModel, readOnlyCollection, typeArgs);
            CSharp.TypeName readOnlyCollectionTypeName = CSharp.TypeName.New(globalSystemCollectionsObjectModelReadOnlyCollection);
            CSharp.Type readOnlyCollectionType = CSharp.Type.NewNamedClass(readOnlyCollectionTypeName);
            CSharp.RankSpecifier specifier = CSharp.RankSpecifier.New(1);
            CSharp.RankSpecifiers rank = CSharp.RankSpecifiers.New(Sequence.Create(specifier));
            CSharp.ArrayType byteArrayType = CSharp.ArrayType.New(CSharp.NonArrayType.New(CSharp.Type.NewByte()), rank);
            Sequence<CSharp.VariableInitializer> items = Sequence.GetEmpty<CSharp.VariableInitializer>();
            foreach (byte item in value)
                items = Sequence.Append(items, CSharp.VariableInitializer.NewSingle(CSharp.Expression.NewLiteral(CSharp.Literal.NewInteger(item))));
            CSharp.ArrayInitializer values = CSharp.ArrayInitializer.New(value.Count == 0 ? null : CSharp.VariableInitializerList.New(items));
            CSharp.Argument argArray = CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(CSharp.Expression.NewArrayCreationWithArrayType(byteArrayType, values)));
            CSharp.ArgumentList args = CSharp.ArgumentList.New(Sequence.Create(argArray));
            return CSharp.Expression.NewObjectCreation(readOnlyCollectionType, args);
        }

        public virtual CSharp.Expression TranslateIdentifier(string name)
        {
            if (name == null)
                throw new ArgumentNullException(nameof(name));
            return CSharp.Expression.NewSimpleName(CSharp.SimpleName.New(CSharp.Identifier.New(name)));
        }

        public virtual GrammarProduction CurrentProduction { get; set; }

        public virtual int CheckSlotNumber(int num, GrammarProduction prod, SourceContext context)
        {
            if (prod == null)
                throw new ArgumentNullException(nameof(prod));
            if (num <= 0)
            {
                SyntaxErrorException e = new SyntaxErrorException(SR.SlotNumberMustBePositive);
                e.AddLocation(context);
                throw e;
            }
            if (num > prod.Length)
            {
                SyntaxErrorException e = new SyntaxErrorException(SR.SlotNumberOutOfRange);
                e.AddLocation(context);
                throw e;
            }
            return prod.Length - num + 1;
        }

        public virtual void CheckSlotType(GrammarSymbol sym, SourceContext context)
        {
            if (sym == null)
                throw new ArgumentNullException(nameof(sym));
            if (!sym.HasSemanticValue)
            {
                string message = string.Format(SR.GrammarSymbolHasNoSemanticValue, sym.Name);
                SyntaxErrorException e = new SyntaxErrorException(message);
                e.AddLocation(sym.Context);
                e.AddLocation(context);
                throw e;
            }
        }
        #endregion

        #region expressions
        public virtual CSharp.Expression TranslateExpression(Expression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return n.AcceptExpressionTranslator(this);
        }

        public virtual CSharp.Expression TranslateNullExpression(NullExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Expression.NewLiteral(CSharp.Literal.NewNull());
        }

        public virtual CSharp.Expression TranslateBooleanExpression(BooleanExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return TranslateBooleanLiteral(n.Value.Value);
        }

        public virtual CSharp.Expression TranslateIntegerExpression(IntegerExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return TranslateIntegerLiteral(n.Value.Value, n.Context);
        }

        public virtual CSharp.Expression TranslateFloatExpression(FloatExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return TranslateFloatLiteral(n.Value.Value);
        }

        public virtual CSharp.Expression TranslateComplexExpression(ComplexExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return TranslateComplexLiteral(n.Value.Value);
        }

        public virtual CSharp.Expression TranslateStringExpression(StringExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return TranslateStringLiteral(n.Value.Value);
        }

        public virtual CSharp.Expression TranslateByteStringExpression(ByteStringExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return TranslateByteStringLiteral(n.Value.Value);
        }

        public virtual CSharp.Expression TranslateQuoteStringExpression(QuoteStringExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return TranslateQuoteLiteral(n.Value.Value);
        }

        public virtual CSharp.Expression TranslateQuoteByteStringExpression(QuoteByteStringExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return TranslateByteStringLiteral(n.Value.Value);
        }

        public virtual CSharp.Expression TranslateStringSeriesExpression(StringSeriesExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            StringBuilder sb = new StringBuilder();
            foreach (StringLiteral item in n.Values)
                sb.Append(item.Value);
            return TranslateStringLiteral(sb.ToString());
        }

        public virtual CSharp.Expression TranslateByteStringSeriesExpression(ByteStringSeriesExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            List<byte> bsb = new List<byte>();
            foreach (ByteStringLiteral item in n.Values)
                bsb.AddRange(item.Value);
            ReadOnlyCollection<byte> value = new ReadOnlyCollection<byte>(bsb.ToArray());
            return TranslateByteStringLiteral(value);
        }

        public virtual CSharp.Expression TranslateQuoteStringSeriesExpression(QuoteStringSeriesExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            StringBuilder sb = new StringBuilder();
            foreach (StringLiteral item in n.Values)
                sb.Append(item.Value);
            return TranslateStringLiteral(sb.ToString());
        }

        public virtual CSharp.Expression TranslateQuoteByteStringSeriesExpression(QuoteByteStringSeriesExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            List<byte> bsb = new List<byte>();
            foreach (ByteStringLiteral item in n.Values)
                bsb.AddRange(item.Value);
            ReadOnlyCollection<byte> value = new ReadOnlyCollection<byte>(bsb.ToArray());
            return TranslateByteStringLiteral(value);
        }

        public virtual CSharp.Expression TranslateJoinedStringExpression(JoinedStringExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateJoinedString);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Expression TranslateFormattedValueExpression(FormattedValueExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateFormattedValue);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Expression TranslateNameReferenceExpression(NameReferenceExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return TranslateIdentifier(n.Name.Name);
        }

        public virtual CSharp.Expression TranslateBuiltinTypeReferenceExpression(BuiltinTypeReferenceExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.PredefinedTypeCanNotBeUsedAlone);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Expression TranslateNamespaceOrTypeNameAsExpression(CSharp.NamespaceOrTypeName n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.IsUnqualified)
            {
                var id = n.AsUnqualified;
                var name = CSharp.SimpleName.New(id.Name, id.TypeArguments);
                return CSharp.Expression.NewSimpleName(name);
            }
            else if (n.IsQualified)
            {
                var qid = n.AsQualified;
                if (qid.Operand.IsQualifiedAliasMember && qid.TypeArguments == null)
                {
                    var qa = qid.Operand.AsQualifiedAliasMember;
                    return CSharp.Expression.NewQualifiedAliasMemberAccess(qa.Member, qid.Name);
                }
                var operand = TranslateNamespaceOrTypeNameAsExpression(qid.Operand);
                return CSharp.Expression.NewObjectMemberAccess(operand, qid.Name, qid.TypeArguments);
            }
            else
            {
                SyntaxErrorException e = new SyntaxErrorException(SR.CanNotBeTranslatedAsExpression);
                e.AddLocation(n.Context);
                throw e;
            }
        }

        public virtual CSharp.Expression TranslateTypeReferenceExpression(TypeReferenceExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.NamespaceOrTypeName type = TranslateTypeName(n.Type);
            return TranslateNamespaceOrTypeNameAsExpression(type);
        }

        public virtual CSharp.Expression TranslateSlotValueReferenceExpression(SlotValueReferenceExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (CurrentProduction == null)
            {
                RuntimeErrorException e = new RuntimeErrorException(SR.CurrentProductionNotAvailableCanNotTranslateSlotValueReference);
                e.AddLocation(n.Context);
                throw e;
            }
            int offset = CheckSlotNumber(n.Slot.AsNativeInt, CurrentProduction, n.Context);
            GrammarSymbol sym = CurrentProduction.Symbols[n.Slot.AsNativeInt - 1];
            CheckSlotType(sym, n.Context);
            Expression values = Expression.NewNameReference(Identifier.New("_values"));
            Expression count = Expression.NewAccess(values, Identifier.New("Count"));
            Expression index = Expression.NewSubtract(count, Expression.NewInteger(IntegerLiteral.New(offset)));
            Expression value = Expression.NewSubscript(values, SubscriptList.New(Sequence.Create(Subscript.NewIndex(index)), false));
            Expression cast = Expression.NewAsInstanceOf(value, sym.Type);
            return TranslateExpression(cast);
        }

        public virtual CSharp.Expression TranslateSlotContextReferenceExpression(SlotContextReferenceExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (CurrentProduction == null)
            {
                RuntimeErrorException e = new RuntimeErrorException(SR.CurrentProductionNotAvailableCanNotTranslateSlotContextReference);
                e.AddLocation(n.Context);
                throw e;
            }
            int offset = CheckSlotNumber(n.Slot.AsNativeInt, CurrentProduction, n.Context);
            Expression contexts = Expression.NewNameReference(Identifier.New("_contexts"));
            Expression count = Expression.NewAccess(contexts, Identifier.New("Count"));
            Expression index = Expression.NewSubtract(count, Expression.NewInteger(IntegerLiteral.New(offset)));
            Expression context = Expression.NewSubscript(contexts, SubscriptList.New(Sequence.Create(Subscript.NewIndex(index)), false));
            return TranslateExpression(context);
        }

        public virtual CSharp.Expression TranslateResultValueReferenceExpression(ResultValueReferenceExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (CurrentProduction == null)
            {
                RuntimeErrorException e = new RuntimeErrorException(SR.CurrentProductionNotAvailableCanNotTranslateResultValueReference);
                e.AddLocation(n.Context);
                throw e;
            }
            return TranslateIdentifier("result");
        }

        public virtual CSharp.Expression TranslateResultContextReferenceExpression(ResultContextReferenceExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (CurrentProduction == null)
            {
                RuntimeErrorException e = new RuntimeErrorException(SR.CurrentProductionNotAvailableCanNotTranslateResultContextReference);
                e.AddLocation(n.Context);
                throw e;
            }
            return TranslateIdentifier("_nodeContext");
        }

        public virtual CSharp.Expression TranslateThisReferenceExpression(ThisReferenceExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Expression.NewThisAccess();
        }

        public virtual CSharp.Expression TranslateBaseReferenceExpression(BaseReferenceExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.BaseCanNotBeUsedAlone);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Expression TranslateEllipsisExpression(EllipsisExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateEllipsis);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Expression TranslateUnitExpression(UnitExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Expression.NewLiteral(CSharp.Literal.NewNull());
        }

        public virtual CSharp.Expression TranslateEmptyListExpression(EmptyListExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateEmptyList);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Expression TranslateEmptySetExpression(EmptySetExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateEmptySet);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Expression TranslateEmptyMapExpression(EmptyMapExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateEmptyMap);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Expression TranslateGroupExpression(GroupExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return TranslateExpression(n.Operand);
        }

        public virtual CSharp.Expression TranslateTupleExpression(TupleExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            List<CSharp.Expression> list = new List<CSharp.Expression>();
            foreach (Expression e in n.Elements)
            {
                CSharp.Expression item = TranslateExpression(e);
                list.Add(item);
            }
            bool first = true;
            while (true)
            {
                int num = 8;
                if (first)
                {
                    first = false;
                    num = list.Count % 7;
                    if (num == 0)
                        num = 7;
                }
                Sequence<CSharp.Expression> items = Sequence.New(list.GetRange(list.Count - num, num));
                list.RemoveRange(list.Count - num, num);
                CSharp.Identifier global = CSharp.Identifier.New("global");
                CSharp.Identifier system = CSharp.Identifier.New("System");
                CSharp.Identifier tuple = CSharp.Identifier.New("Tuple");
                CSharp.Identifier create = CSharp.Identifier.New("Create");
                Sequence<CSharp.Argument> argItems = items.Map(e => CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(e)));
                CSharp.ArgumentList argsItems = CSharp.ArgumentList.New(argItems);
                CSharp.QualifiedAliasMember globalSystem = CSharp.QualifiedAliasMember.New(global, system);
                CSharp.Expression globalSystemTuple = CSharp.Expression.NewQualifiedAliasMemberAccess(globalSystem, tuple);
                CSharp.Expression tupleCreate = CSharp.Expression.NewObjectMemberAccess(globalSystemTuple, create);
                CSharp.Expression call = CSharp.Expression.NewInvocation(tupleCreate, argsItems);
                if (list.Count == 0)
                    return call;
                list.Add(call);
            }
        }

        public virtual CSharp.Expression TranslateRecordExpression(RecordExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            Sequence<CSharp.MemberDeclarator> declarators = Sequence.GetEmpty<CSharp.MemberDeclarator>();
            foreach (FieldLabelValuePair field in n.Fields)
            {
                CSharp.Identifier name = CSharp.Identifier.New(field.Label.Name);
                CSharp.Expression value = TranslateExpression(field.Value);
                CSharp.MemberDeclarator declarator = CSharp.MemberDeclarator.NewBinding(name, value);
                declarators = Sequence.Append(declarators, declarator);
            }
            CSharp.MemberDeclaratorList list = CSharp.MemberDeclaratorList.New(declarators);
            CSharp.AnonymousObjectInitializer init = CSharp.AnonymousObjectInitializer.New(list);
            return CSharp.Expression.NewAnonymousObjectCreation(init);
        }

        public virtual CSharp.Expression TranslateValueTupleExpression(ValueTupleExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.Elements.Count == 1)
            {
                CSharp.Identifier global = CSharp.Identifier.New("global");
                CSharp.Identifier system = CSharp.Identifier.New("System");
                CSharp.Identifier valueTuple = CSharp.Identifier.New("ValueTuple");
                CSharp.Identifier create = CSharp.Identifier.New("Create");
                CSharp.Expression item = TranslateExpression(n.Elements[0]);
                CSharp.Argument argItem = CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(item));
                CSharp.ArgumentList argsItem = CSharp.ArgumentList.New(Sequence.Create(argItem));
                CSharp.QualifiedAliasMember globalSystem = CSharp.QualifiedAliasMember.New(global, system);
                CSharp.Expression globalSystemValueTuple = CSharp.Expression.NewQualifiedAliasMemberAccess(globalSystem, valueTuple);
                CSharp.Expression valueTupleCreate = CSharp.Expression.NewObjectMemberAccess(globalSystemValueTuple, create);
                CSharp.Expression call = CSharp.Expression.NewInvocation(valueTupleCreate, argsItem);
                return call;
            }
            Sequence<CSharp.Expression> items = n.Elements.Map(e => TranslateExpression(e));
            CSharp.ExpressionList args = CSharp.ExpressionList.New(items);
            return CSharp.Expression.NewValueTupleCreation(args);
        }

        public virtual CSharp.Expression TranslateValueRecordExpression(ValueRecordExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateValueRecord);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Expression TranslateListExpression(ListExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier parserGenerator = CSharp.Identifier.New("ParserGenerator");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier sequence = CSharp.Identifier.New("Sequence");
            CSharp.Identifier create = CSharp.Identifier.New("Create");
            Sequence<CSharp.Argument> argItems = n.Elements.Map(e => CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(TranslateExpression(e))));
            CSharp.ArgumentList argsItems = CSharp.ArgumentList.New(argItems);
            CSharp.QualifiedAliasMember globalParserGenerator = CSharp.QualifiedAliasMember.New(global, parserGenerator);
            CSharp.Expression globalParserGeneratorCollections = CSharp.Expression.NewQualifiedAliasMemberAccess(globalParserGenerator, collections);
            CSharp.Expression globalParserGeneratorCollectionsSequence = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollections, sequence);
            CSharp.Expression sequenceCreate = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollectionsSequence, create);
            CSharp.Expression call = CSharp.Expression.NewInvocation(sequenceCreate, argsItems);
            return call;
        }

        public virtual CSharp.Expression TranslateSetExpression(SetExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier parserGenerator = CSharp.Identifier.New("ParserGenerator");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier readOnlySet = CSharp.Identifier.New("ReadOnlySet");
            CSharp.Identifier create = CSharp.Identifier.New("Create");
            Sequence<CSharp.Argument> argItems = n.Elements.Map(e => CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(TranslateExpression(e))));
            CSharp.ArgumentList argsItems = CSharp.ArgumentList.New(argItems);
            CSharp.QualifiedAliasMember globalParserGenerator = CSharp.QualifiedAliasMember.New(global, parserGenerator);
            CSharp.Expression globalParserGeneratorCollections = CSharp.Expression.NewQualifiedAliasMemberAccess(globalParserGenerator, collections);
            CSharp.Expression globalParserGeneratorCollectionsReadOnlySet = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollections, readOnlySet);
            CSharp.Expression readOnlySetCreate = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollectionsReadOnlySet, create);
            CSharp.Expression call = CSharp.Expression.NewInvocation(readOnlySetCreate, argsItems);
            return call;
        }

        public virtual CSharp.Expression TranslateMapExpression(MapExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier parserGenerator = CSharp.Identifier.New("ParserGenerator");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier readOnlyDictionary = CSharp.Identifier.New("ReadOnlyDictionary");
            CSharp.Identifier create = CSharp.Identifier.New("Create");
            Sequence<CSharp.Argument> argItems = n.Elements.Map(e =>
            {
                CSharp.Identifier global2 = CSharp.Identifier.New("global");
                CSharp.Identifier parserGenerator2 = CSharp.Identifier.New("ParserGenerator");
                CSharp.Identifier collections2 = CSharp.Identifier.New("Collections");
                CSharp.Identifier keyValuePair = CSharp.Identifier.New("KeyValuePair");
                CSharp.Identifier create2 = CSharp.Identifier.New("Create");
                Sequence<CSharp.Argument> argItems2 = Sequence.Create(
                    CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(TranslateExpression(e.Key))),
                    CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(TranslateExpression(e.Value)))
                );
                CSharp.ArgumentList argsItems2 = CSharp.ArgumentList.New(argItems2);
                CSharp.QualifiedAliasMember globalParserGenerator2 = CSharp.QualifiedAliasMember.New(global2, parserGenerator2);
                CSharp.Expression globalParserGeneratorCollections2 = CSharp.Expression.NewQualifiedAliasMemberAccess(globalParserGenerator2, collections2);
                CSharp.Expression globalParserGeneratorCollectionsKeyValuePair = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollections2, keyValuePair);
                CSharp.Expression keyValuePairCreate = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollectionsKeyValuePair, create2);
                CSharp.Expression call2 = CSharp.Expression.NewInvocation(keyValuePairCreate, argsItems2);
                return CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(call2));
            });
            CSharp.ArgumentList argsItems = CSharp.ArgumentList.New(argItems);
            CSharp.QualifiedAliasMember globalParserGenerator = CSharp.QualifiedAliasMember.New(global, parserGenerator);
            CSharp.Expression globalParserGeneratorCollections = CSharp.Expression.NewQualifiedAliasMemberAccess(globalParserGenerator, collections);
            CSharp.Expression globalParserGeneratorCollectionsReadOnlyDictionary = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollections, readOnlyDictionary);
            CSharp.Expression readOnlyDictionaryCreate = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollectionsReadOnlyDictionary, create);
            CSharp.Expression call = CSharp.Expression.NewInvocation(readOnlyDictionaryCreate, argsItems);
            return call;
        }

        public virtual CSharp.Expression TranslateComprehension(ComprehensionList n, CSharp.Expression selector)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (selector == null)
                throw new ArgumentNullException(nameof(selector));
            CSharp.FromClause firstFromClause = null;
            Sequence<CSharp.QueryBodyClause> queryBodyClauses = Sequence.GetEmpty<CSharp.QueryBodyClause>();
            foreach (Comprehension item in n.Items)
            {
                if (item.IsAsync)
                {
                    RuntimeErrorException e = new RuntimeErrorException(SR.CanNotTranslateAsyncComprehension);
                    e.AddLocation(n.Context);
                    e.AddLocation(item.Context);
                    throw e;
                }
                if (!item.Enumerator.IsNameReference)
                {
                    RuntimeErrorException e = new RuntimeErrorException(SR.CanNotTranslateComprehensionWithComplexEnumerators);
                    e.AddLocation(n.Context);
                    e.AddLocation(item.Enumerator.Context);
                    throw e;
                }
                CSharp.Identifier enumerator = CSharp.Identifier.New(item.Enumerator.AsNameReference.Name.Name);
                CSharp.Expression enumerable = TranslateExpression(item.Enumerable);
                CSharp.FromClause fromClause = CSharp.FromClause.New(null, enumerator, enumerable);
                if (firstFromClause == null)
                    firstFromClause = fromClause;
                else
                    queryBodyClauses = Sequence.Append(queryBodyClauses, CSharp.QueryBodyClause.NewFrom(fromClause));
                foreach (ComprehensionFilter filter in item.Filters.Items)
                {
                    CSharp.Expression test = TranslateExpression(filter.Condition);
                    CSharp.BooleanExpression condition = CSharp.BooleanExpression.New(test);
                    CSharp.WhereClause whereClause = CSharp.WhereClause.New(condition);
                    queryBodyClauses = Sequence.Append(queryBodyClauses, CSharp.QueryBodyClause.NewWhere(whereClause));
                }
            }
            CSharp.SelectClause selectClause = CSharp.SelectClause.New(selector);
            CSharp.SelectOrGroupClause selectorClause = CSharp.SelectOrGroupClause.NewSelect(selectClause);
            CSharp.QueryBodyClauses clauses = null;
            if (queryBodyClauses.Count > 0)
                clauses = CSharp.QueryBodyClauses.New(queryBodyClauses);
            CSharp.QueryBody queryBody = CSharp.QueryBody.New(clauses, selectorClause);
            return CSharp.Expression.NewQuery(firstFromClause, queryBody);
        }

        public virtual CSharp.Expression TranslateGeneratorExpression(GeneratorExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return TranslateComprehension(n.Comprehensions, TranslateExpression(n.Element));
        }

        public virtual CSharp.Expression TranslateListComprehensionExpression(ListComprehensionExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier parserGenerator = CSharp.Identifier.New("ParserGenerator");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier sequence = CSharp.Identifier.New("Sequence");
            CSharp.Identifier newSeq = CSharp.Identifier.New("New");
            CSharp.Expression argItem = TranslateComprehension(n.Comprehensions, TranslateExpression(n.Element));
            Sequence<CSharp.Argument> argItems = Sequence.Create(CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(argItem)));
            CSharp.ArgumentList argsItems = CSharp.ArgumentList.New(argItems);
            CSharp.QualifiedAliasMember globalParserGenerator = CSharp.QualifiedAliasMember.New(global, parserGenerator);
            CSharp.Expression globalParserGeneratorCollections = CSharp.Expression.NewQualifiedAliasMemberAccess(globalParserGenerator, collections);
            CSharp.Expression globalParserGeneratorCollectionsSequence = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollections, sequence);
            CSharp.Expression sequenceNew = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollectionsSequence, newSeq);
            CSharp.Expression call = CSharp.Expression.NewInvocation(sequenceNew, argsItems);
            return call;
        }

        public virtual CSharp.Expression TranslateSetComprehensionExpression(SetComprehensionExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier parserGenerator = CSharp.Identifier.New("ParserGenerator");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier readOnlySet = CSharp.Identifier.New("ReadOnlySet");
            CSharp.Identifier newSet = CSharp.Identifier.New("New");
            CSharp.Expression argItem = TranslateComprehension(n.Comprehensions, TranslateExpression(n.Element));
            Sequence<CSharp.Argument> argItems = Sequence.Create(CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(argItem)));
            CSharp.ArgumentList argsItems = CSharp.ArgumentList.New(argItems);
            CSharp.QualifiedAliasMember globalParserGenerator = CSharp.QualifiedAliasMember.New(global, parserGenerator);
            CSharp.Expression globalParserGeneratorCollections = CSharp.Expression.NewQualifiedAliasMemberAccess(globalParserGenerator, collections);
            CSharp.Expression globalParserGeneratorCollectionsReadOnlySet = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollections, readOnlySet);
            CSharp.Expression readOnlySetNew = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollectionsReadOnlySet, newSet);
            CSharp.Expression call = CSharp.Expression.NewInvocation(readOnlySetNew, argsItems);
            return call;
        }

        public virtual CSharp.Expression TranslateMapComprehensionExpression(MapComprehensionExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier parserGenerator = CSharp.Identifier.New("ParserGenerator");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier readOnlyDictionary = CSharp.Identifier.New("ReadOnlyDictionary");
            CSharp.Identifier keyValuePair = CSharp.Identifier.New("KeyValuePair");
            CSharp.Identifier newDict = CSharp.Identifier.New("New");
            CSharp.Identifier create = CSharp.Identifier.New("Create");
            CSharp.QualifiedAliasMember globalParserGenerator = CSharp.QualifiedAliasMember.New(global, parserGenerator);
            CSharp.Expression globalParserGeneratorCollections = CSharp.Expression.NewQualifiedAliasMemberAccess(globalParserGenerator, collections);
            CSharp.Expression globalParserGeneratorCollectionsReadOnlyDictionary = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollections, readOnlyDictionary);
            CSharp.Expression globalParserGeneratorCollectionsKeyValuePair = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollections, keyValuePair);
            CSharp.Expression readOnlyDictionaryNew = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollectionsReadOnlyDictionary, newDict);
            CSharp.Expression keyValuePairCreate = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollectionsKeyValuePair, create);
            Sequence<CSharp.Argument> keyValueItems = Sequence.Create(
                CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(TranslateExpression(n.Key))),
                CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(TranslateExpression(n.Value)))
            );
            CSharp.ArgumentList keyValueArgs = CSharp.ArgumentList.New(keyValueItems);
            CSharp.Expression pair = CSharp.Expression.NewInvocation(keyValuePairCreate, keyValueArgs);
            CSharp.Expression argItem = TranslateComprehension(n.Comprehensions, pair);
            Sequence<CSharp.Argument> argItems = Sequence.Create(CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(argItem)));
            CSharp.ArgumentList argsItems = CSharp.ArgumentList.New(argItems);
            CSharp.Expression call = CSharp.Expression.NewInvocation(readOnlyDictionaryNew, argsItems);
            return call;
        }

        public virtual CSharp.Expression TranslateAccessExpression(AccessExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier member = CSharp.Identifier.New(n.Member.Name);
            if (n.Operand.IsBuiltinTypeReference)
            {
                switch (n.Operand.AsBuiltinTypeReference.Type.Tag)
                {
                    case TypeExpressionCategory.Int8: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewSByte(), member);
                    case TypeExpressionCategory.Int16: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewShort(), member);
                    case TypeExpressionCategory.Int32: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewInt(), member);
                    case TypeExpressionCategory.Int64: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewLong(), member);

                    case TypeExpressionCategory.UInt8: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewByte(), member);
                    case TypeExpressionCategory.UInt16: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewUShort(), member);
                    case TypeExpressionCategory.UInt32: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewUInt(), member);
                    case TypeExpressionCategory.UInt64: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewULong(), member);

                    case TypeExpressionCategory.Float32: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewFloat(), member);
                    case TypeExpressionCategory.Float64: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewDouble(), member);

                    case TypeExpressionCategory.Char8: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewByte(), member);
                    case TypeExpressionCategory.Char16: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewChar(), member);
                    case TypeExpressionCategory.Char32: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewInt(), member);

                    case TypeExpressionCategory.SByte: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewSByte(), member);
                    case TypeExpressionCategory.Short: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewShort(), member);
                    case TypeExpressionCategory.Int: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewInt(), member);
                    case TypeExpressionCategory.Long: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewLong(), member);

                    case TypeExpressionCategory.Byte: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewByte(), member);
                    case TypeExpressionCategory.UShort: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewUShort(), member);
                    case TypeExpressionCategory.UInt: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewUInt(), member);
                    case TypeExpressionCategory.ULong: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewULong(), member);

                    case TypeExpressionCategory.IntPtrT:
                    case TypeExpressionCategory.SSizeT:
                    case TypeExpressionCategory.PtrDiffT:
                        {
                            CSharp.Identifier global = CSharp.Identifier.New("global");
                            CSharp.Identifier system = CSharp.Identifier.New("System");
                            CSharp.Identifier intPtr = CSharp.Identifier.New("IntPtr");
                            CSharp.QualifiedAliasMember globalSystem = CSharp.QualifiedAliasMember.New(global, system);
                            CSharp.Expression globalSystemIntPtr = CSharp.Expression.NewQualifiedAliasMemberAccess(globalSystem, intPtr);
                            return CSharp.Expression.NewObjectMemberAccess(globalSystemIntPtr, member);
                        }

                    case TypeExpressionCategory.UIntPtrT:
                    case TypeExpressionCategory.SizeT:
                        {
                            CSharp.Identifier global = CSharp.Identifier.New("global");
                            CSharp.Identifier system = CSharp.Identifier.New("System");
                            CSharp.Identifier uintPtr = CSharp.Identifier.New("UIntPtr");
                            CSharp.QualifiedAliasMember globalSystem = CSharp.QualifiedAliasMember.New(global, system);
                            CSharp.Expression globalSystemUIntPtr = CSharp.Expression.NewQualifiedAliasMemberAccess(globalSystem, uintPtr);
                            return CSharp.Expression.NewObjectMemberAccess(globalSystemUIntPtr, member);
                        }

                    case TypeExpressionCategory.Float: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewFloat(), member);
                    case TypeExpressionCategory.Double: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewDouble(), member);
                    case TypeExpressionCategory.Decimal: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewDecimal(), member);

                    case TypeExpressionCategory.Bool: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewBool(), member);
                    case TypeExpressionCategory.Char: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewChar(), member);

                    case TypeExpressionCategory.String: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewString(), member);
                    case TypeExpressionCategory.Object: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewObject(), member);
                    case TypeExpressionCategory.Dynamic: return CSharp.Expression.NewPredefinedTypeMemberAccess(CSharp.PredefinedType.NewObject(), member);

                    default: throw new InvalidOperationException(SR.InvalidBuiltinTypeCode);
                }
            }
            else if (n.Operand.IsTypeReference)
            {
                CSharp.NamespaceOrTypeName typeName = TranslateTypeName(n.Operand.AsTypeReference.Type);
                if (typeName.IsQualifiedAliasMember)
                {
                    var qa = typeName.AsQualifiedAliasMember;
                    return CSharp.Expression.NewQualifiedAliasMemberAccess(qa.Member, member);
                }
                CSharp.Expression expr = TranslateNamespaceOrTypeNameAsExpression(typeName);
                return CSharp.Expression.NewObjectMemberAccess(expr, member);
            }
            else if (n.Operand.IsCall && n.Operand.AsCall.Operand.IsNameReference)
            {
                string func = n.Operand.AsCall.Operand.AsNameReference.Name.Name;
                if (func == "super")
                    return CSharp.Expression.NewBaseMemberAccess(member);
            }
            CSharp.Expression operand = TranslateExpression(n.Operand);
            return CSharp.Expression.NewObjectMemberAccess(operand, member);
        }

        public virtual CSharp.Expression TranslateNullableAccessExpression(NullableAccessExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression operand = TranslateExpression(n.Operand);
            CSharp.Identifier member = CSharp.Identifier.New(n.Member.Name);
            return CSharp.Expression.NewNullableObjectMemberAccess(operand, member);
        }

        public virtual CSharp.ArgumentList TranslateArgumentList(ArgumentList n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.Items.Count == 0)
                return null;
            Sequence<CSharp.Argument> items = Sequence.GetEmpty<CSharp.Argument>();
            foreach (Argument arg in n.Items)
            {
                if (arg.IsPositional)
                {
                    CSharp.Argument item = CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(TranslateExpression(arg.AsPositional.Value)));
                    items = Sequence.Append(items, item);
                }
                else if (arg.IsKeyword)
                {
                    CSharp.Argument item = CSharp.Argument.New(CSharp.ArgumentName.New(CSharp.Identifier.New(arg.AsKeyword.Name.Name)), CSharp.ArgumentValue.NewIn(TranslateExpression(arg.AsKeyword.Value)));
                    items = Sequence.Append(items, item);
                }
                else if (arg.IsPositionalUnpack)
                {
                    SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateUnpackingArgument);
                    e.AddLocation(n.Context);
                    throw e;
                }
                else
                {
                    SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateKeywordUnpackingArgument);
                    e.AddLocation(n.Context);
                    throw e;
                }
            }
            return CSharp.ArgumentList.New(items);
        }

        public virtual CSharp.Expression TranslateCallExpression(CallExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.Operand.IsNameReference)
            {
                string func = n.Operand.AsNameReference.Name.Name;
                if (func == "print")
                {
                    CSharp.Identifier global = CSharp.Identifier.New("global");
                    CSharp.Identifier system = CSharp.Identifier.New("System");
                    CSharp.Identifier console = CSharp.Identifier.New("Console");
                    CSharp.Identifier writeLine = CSharp.Identifier.New("WriteLine");
                    CSharp.ArgumentList argItems = TranslateArgumentList(n.Arguments);
                    CSharp.QualifiedAliasMember globalSystem = CSharp.QualifiedAliasMember.New(global, system);
                    CSharp.Expression globalSystemConsole = CSharp.Expression.NewQualifiedAliasMemberAccess(globalSystem, console);
                    CSharp.Expression consoleWriteLine = CSharp.Expression.NewObjectMemberAccess(globalSystemConsole, writeLine);
                    return CSharp.Expression.NewInvocation(consoleWriteLine, argItems);
                }
                if (func == "range" || func == "xrange")
                {
                    CSharp.Identifier global = CSharp.Identifier.New("global");
                    CSharp.Identifier system = CSharp.Identifier.New("System");
                    CSharp.Identifier linq = CSharp.Identifier.New("Linq");
                    CSharp.Identifier enumerable = CSharp.Identifier.New("Enumerable");
                    CSharp.Identifier range = CSharp.Identifier.New("Range");
                    CSharp.ArgumentList argItems = TranslateArgumentList(n.Arguments);
                    if (argItems != null && argItems.Items.Count == 1)
                        argItems = argItems.WithItems(Sequence.Prepend(CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(CSharp.Expression.NewLiteral(CSharp.Literal.NewInteger(0)))), argItems.Items));
                    CSharp.QualifiedAliasMember globalSystem = CSharp.QualifiedAliasMember.New(global, system);
                    CSharp.Expression globalSystemLinq = CSharp.Expression.NewQualifiedAliasMemberAccess(globalSystem, linq);
                    CSharp.Expression globalSystemLinqEnumerable = CSharp.Expression.NewObjectMemberAccess(globalSystemLinq, enumerable);
                    CSharp.Expression enumerableRange = CSharp.Expression.NewObjectMemberAccess(globalSystemLinqEnumerable, range);
                    return CSharp.Expression.NewInvocation(enumerableRange, argItems);
                }
            }
            CSharp.Expression operand = TranslateExpression(n.Operand);
            CSharp.ArgumentList args = TranslateArgumentList(n.Arguments);
            return CSharp.Expression.NewInvocation(operand, args);
        }

        public virtual CSharp.Expression TranslateSubscriptExpression(SubscriptExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (!Enumerable.All(n.Subscripts.Items, x => x.IsIndex))
            {
                SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateComplexSubscripts);
                e.AddLocation(n.Context);
                throw e;
            }
            CSharp.Expression operand = TranslateExpression(n.Operand);
            Sequence<CSharp.Expression> subscripts = n.Subscripts.Items.Map(x => TranslateExpression(x.AsIndex.Value));
            CSharp.ExpressionList args = CSharp.ExpressionList.New(subscripts);
            if (!operand.IsPrimaryNoArrayCreation)
                operand = CSharp.Expression.NewParenthesized(operand);
            return CSharp.Expression.NewElementAccess(operand.AsPrimaryNoArrayCreation, args);
        }

        public virtual CSharp.Expression TranslateNewExpression(NewExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.ArgumentList args = TranslateArgumentList(n.Arguments);
            return CSharp.Expression.NewObjectCreation(type, args);
        }

        public virtual CSharp.Expression TranslateDefaultExpression(DefaultExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Expression.NewDefaultValue(TranslateTypeExpression(n.Type));
        }

        public virtual CSharp.Expression TranslateTypeOfExpression(TypeOfExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.Type.IsUnit)
                return CSharp.Expression.NewVoidTypeof();
            try
            {
                CSharp.UnboundTypeName typeName = TranslateUnboundTypeName(n.Type);
                return CSharp.Expression.NewUnboundTypeof(typeName);
            }
            catch (SyntaxErrorException e)
            {
                if (e.Message != SR.CanNotBeTranslatedAsUnboundTypeName)
                    throw;
            }
            return CSharp.Expression.NewTypeof(TranslateTypeExpression(n.Type));
        }

        public virtual CSharp.NamedEntity TranslateExpressionAsNamedEntity(Expression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.IsNameReference)
            {
                var name = n.AsNameReference;
                var id = CSharp.Identifier.New(name.Name.Name);
                var sn = CSharp.SimpleName.New(id);
                return CSharp.NamedEntity.NewSimple(sn);
            }
            else if (n.IsAccess)
            {
                var access = n.AsAccess;
                var operand = TranslateExpressionAsNamedEntityTarget(access.Operand);
                var member = CSharp.Identifier.New(access.Member.Name);
                return CSharp.NamedEntity.NewQualified(operand, member);
            }
            else
            {
                SyntaxErrorException e = new SyntaxErrorException(SR.CanNotBeTranslatedAsNamedEntity);
                e.AddLocation(n.Context);
                throw e;
            }
        }

        public virtual CSharp.NamedEntityTarget TranslateExpressionAsNamedEntityTarget(Expression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.IsThisReference)
                return CSharp.NamedEntityTarget.NewThis();
            else if (n.IsBaseReference)
                return CSharp.NamedEntityTarget.NewBase();
            else if (n.IsBuiltinTypeReference)
            {
                switch (n.AsBuiltinTypeReference.Type.Tag)
                {
                    case TypeExpressionCategory.Int8: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewSByte());
                    case TypeExpressionCategory.Int16: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewShort());
                    case TypeExpressionCategory.Int32: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewInt());
                    case TypeExpressionCategory.Int64: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewLong());

                    case TypeExpressionCategory.UInt8: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewByte());
                    case TypeExpressionCategory.UInt16: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewUShort());
                    case TypeExpressionCategory.UInt32: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewUInt());
                    case TypeExpressionCategory.UInt64: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewULong());

                    case TypeExpressionCategory.Float32: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewFloat());
                    case TypeExpressionCategory.Float64: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewDouble());

                    case TypeExpressionCategory.Char8: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewByte());
                    case TypeExpressionCategory.Char16: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewChar());
                    case TypeExpressionCategory.Char32: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewInt());

                    case TypeExpressionCategory.SByte: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewSByte());
                    case TypeExpressionCategory.Short: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewShort());
                    case TypeExpressionCategory.Int: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewInt());
                    case TypeExpressionCategory.Long: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewLong());

                    case TypeExpressionCategory.Byte: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewByte());
                    case TypeExpressionCategory.UShort: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewUShort());
                    case TypeExpressionCategory.UInt: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewUInt());
                    case TypeExpressionCategory.ULong: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewULong());

                    case TypeExpressionCategory.IntPtrT:
                    case TypeExpressionCategory.SSizeT:
                    case TypeExpressionCategory.PtrDiffT:
                        {
                            CSharp.Identifier global = CSharp.Identifier.New("global");
                            CSharp.Identifier system = CSharp.Identifier.New("System");
                            CSharp.Identifier intPtr = CSharp.Identifier.New("IntPtr");
                            CSharp.QualifiedAliasMember globalSystem = CSharp.QualifiedAliasMember.New(global, system);
                            CSharp.NamedEntityTarget globalSystemTarget = CSharp.NamedEntityTarget.NewQualifiedAliasMember(globalSystem);
                            CSharp.NamedEntity globalSystemIntPtr = CSharp.NamedEntity.NewQualified(globalSystemTarget, intPtr);
                            return CSharp.NamedEntityTarget.NewNamedEntity(globalSystemIntPtr);
                        }

                    case TypeExpressionCategory.UIntPtrT:
                    case TypeExpressionCategory.SizeT:
                        {
                            CSharp.Identifier global = CSharp.Identifier.New("global");
                            CSharp.Identifier system = CSharp.Identifier.New("System");
                            CSharp.Identifier uintPtr = CSharp.Identifier.New("UIntPtr");
                            CSharp.QualifiedAliasMember globalSystem = CSharp.QualifiedAliasMember.New(global, system);
                            CSharp.NamedEntityTarget globalSystemTarget = CSharp.NamedEntityTarget.NewQualifiedAliasMember(globalSystem);
                            CSharp.NamedEntity globalSystemUIntPtr = CSharp.NamedEntity.NewQualified(globalSystemTarget, uintPtr);
                            return CSharp.NamedEntityTarget.NewNamedEntity(globalSystemUIntPtr);
                        }

                    case TypeExpressionCategory.Float: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewFloat());
                    case TypeExpressionCategory.Double: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewDouble());
                    case TypeExpressionCategory.Decimal: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewDecimal());

                    case TypeExpressionCategory.Bool: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewBool());
                    case TypeExpressionCategory.Char: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewChar());

                    case TypeExpressionCategory.String: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewString());
                    case TypeExpressionCategory.Object: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewObject());
                    case TypeExpressionCategory.Dynamic: return CSharp.NamedEntityTarget.NewPredefinedType(CSharp.PredefinedType.NewObject());

                    default: throw new InvalidOperationException(SR.InvalidBuiltinTypeCode);
                }
            }
            else if (n.IsAccess)
            {
                CSharp.NamedEntity entity = TranslateExpressionAsNamedEntity(n);
                return CSharp.NamedEntityTarget.NewNamedEntity(entity);
            }
            else
            {
                SyntaxErrorException e = new SyntaxErrorException(SR.CanNotBeTranslatedAsNamedEntityTarget);
                e.AddLocation(n.Context);
                throw e;
            }
        }

        public virtual CSharp.Expression TranslateNameOfExpression(NameOfExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.NamedEntity entity = TranslateExpressionAsNamedEntity(n.Operand);
            return CSharp.Expression.NewNameof(entity);
        }

        public virtual CSharp.Expression TranslatePostfixIncrementExpression(PostfixIncrementExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression operand = TranslateExpression(n.Operand);
            return CSharp.Expression.NewPostIncrement(operand);
        }

        public virtual CSharp.Expression TranslatePostfixDecrementExpression(PostfixDecrementExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression operand = TranslateExpression(n.Operand);
            return CSharp.Expression.NewPostDecrement(operand);
        }

        public virtual CSharp.Expression TranslateEmptyMutableListExpression(EmptyMutableListExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateEmptyMutableList);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Expression TranslateEmptyMutableSetExpression(EmptyMutableSetExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateEmptyMutableSet);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Expression TranslateEmptyMutableMapExpression(EmptyMutableMapExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateEmptyMutableMap);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Expression TranslateMutableListExpression(MutableListExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier parserGenerator = CSharp.Identifier.New("ParserGenerator");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier list = CSharp.Identifier.New("List");
            CSharp.Identifier create = CSharp.Identifier.New("Create");
            Sequence<CSharp.Argument> argItems = n.Elements.Map(e => CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(TranslateExpression(e))));
            CSharp.ArgumentList argsItems = CSharp.ArgumentList.New(argItems);
            CSharp.QualifiedAliasMember globalParserGenerator = CSharp.QualifiedAliasMember.New(global, parserGenerator);
            CSharp.Expression globalParserGeneratorCollections = CSharp.Expression.NewQualifiedAliasMemberAccess(globalParserGenerator, collections);
            CSharp.Expression globalParserGeneratorCollectionsList = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollections, list);
            CSharp.Expression listCreate = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollectionsList, create);
            CSharp.Expression call = CSharp.Expression.NewInvocation(listCreate, argsItems);
            return call;
        }

        public virtual CSharp.Expression TranslateMutableSetExpression(MutableSetExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier parserGenerator = CSharp.Identifier.New("ParserGenerator");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier hashSet = CSharp.Identifier.New("HashSet");
            CSharp.Identifier create = CSharp.Identifier.New("Create");
            Sequence<CSharp.Argument> argItems = n.Elements.Map(e => CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(TranslateExpression(e))));
            CSharp.ArgumentList argsItems = CSharp.ArgumentList.New(argItems);
            CSharp.QualifiedAliasMember globalParserGenerator = CSharp.QualifiedAliasMember.New(global, parserGenerator);
            CSharp.Expression globalParserGeneratorCollections = CSharp.Expression.NewQualifiedAliasMemberAccess(globalParserGenerator, collections);
            CSharp.Expression globalParserGeneratorCollectionsHashSet = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollections, hashSet);
            CSharp.Expression hashSetCreate = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollectionsHashSet, create);
            CSharp.Expression call = CSharp.Expression.NewInvocation(hashSetCreate, argsItems);
            return call;
        }

        public virtual CSharp.Expression TranslateMutableMapExpression(MutableMapExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier parserGenerator = CSharp.Identifier.New("ParserGenerator");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier dictionary = CSharp.Identifier.New("Dictionary");
            CSharp.Identifier create = CSharp.Identifier.New("Create");
            Sequence<CSharp.Argument> argItems = n.Elements.Map(e =>
            {
                CSharp.Identifier global2 = CSharp.Identifier.New("global");
                CSharp.Identifier parserGenerator2 = CSharp.Identifier.New("ParserGenerator");
                CSharp.Identifier collections2 = CSharp.Identifier.New("Collections");
                CSharp.Identifier keyValuePair = CSharp.Identifier.New("KeyValuePair");
                CSharp.Identifier create2 = CSharp.Identifier.New("Create");
                Sequence<CSharp.Argument> argItems2 = Sequence.Create(
                    CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(TranslateExpression(e.Key))),
                    CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(TranslateExpression(e.Value)))
                );
                CSharp.ArgumentList argsItems2 = CSharp.ArgumentList.New(argItems2);
                CSharp.QualifiedAliasMember globalParserGenerator2 = CSharp.QualifiedAliasMember.New(global2, parserGenerator2);
                CSharp.Expression globalParserGeneratorCollections2 = CSharp.Expression.NewQualifiedAliasMemberAccess(globalParserGenerator2, collections2);
                CSharp.Expression globalParserGeneratorCollectionsKeyValuePair = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollections2, keyValuePair);
                CSharp.Expression keyValuePairCreate = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollectionsKeyValuePair, create2);
                CSharp.Expression call2 = CSharp.Expression.NewInvocation(keyValuePairCreate, argsItems2);
                return CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(call2));
            });
            CSharp.ArgumentList argsItems = CSharp.ArgumentList.New(argItems);
            CSharp.QualifiedAliasMember globalParserGenerator = CSharp.QualifiedAliasMember.New(global, parserGenerator);
            CSharp.Expression globalParserGeneratorCollections = CSharp.Expression.NewQualifiedAliasMemberAccess(globalParserGenerator, collections);
            CSharp.Expression globalParserGeneratorCollectionsDictionary = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollections, dictionary);
            CSharp.Expression dictionaryCreate = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollectionsDictionary, create);
            CSharp.Expression call = CSharp.Expression.NewInvocation(dictionaryCreate, argsItems);
            return call;
        }

        public virtual CSharp.Expression TranslateMutableListComprehensionExpression(MutableListComprehensionExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier parserGenerator = CSharp.Identifier.New("ParserGenerator");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier list = CSharp.Identifier.New("List");
            CSharp.Identifier newList = CSharp.Identifier.New("New");
            CSharp.Expression argItem = TranslateComprehension(n.Comprehensions, TranslateExpression(n.Element));
            Sequence<CSharp.Argument> argItems = Sequence.Create(CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(argItem)));
            CSharp.ArgumentList argsItems = CSharp.ArgumentList.New(argItems);
            CSharp.QualifiedAliasMember globalParserGenerator = CSharp.QualifiedAliasMember.New(global, parserGenerator);
            CSharp.Expression globalParserGeneratorCollections = CSharp.Expression.NewQualifiedAliasMemberAccess(globalParserGenerator, collections);
            CSharp.Expression globalParserGeneratorCollectionsList = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollections, list);
            CSharp.Expression listNew = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollectionsList, newList);
            CSharp.Expression call = CSharp.Expression.NewInvocation(listNew, argsItems);
            return call;
        }

        public virtual CSharp.Expression TranslateMutableSetComprehensionExpression(MutableSetComprehensionExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier parserGenerator = CSharp.Identifier.New("ParserGenerator");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier hashSet = CSharp.Identifier.New("HashSet");
            CSharp.Identifier newSet = CSharp.Identifier.New("New");
            CSharp.Expression argItem = TranslateComprehension(n.Comprehensions, TranslateExpression(n.Element));
            Sequence<CSharp.Argument> argItems = Sequence.Create(CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(argItem)));
            CSharp.ArgumentList argsItems = CSharp.ArgumentList.New(argItems);
            CSharp.QualifiedAliasMember globalParserGenerator = CSharp.QualifiedAliasMember.New(global, parserGenerator);
            CSharp.Expression globalParserGeneratorCollections = CSharp.Expression.NewQualifiedAliasMemberAccess(globalParserGenerator, collections);
            CSharp.Expression globalParserGeneratorCollectionsHashSet = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollections, hashSet);
            CSharp.Expression hashSetNew = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollectionsHashSet, newSet);
            CSharp.Expression call = CSharp.Expression.NewInvocation(hashSetNew, argsItems);
            return call;
        }

        public virtual CSharp.Expression TranslateMutableMapComprehensionExpression(MutableMapComprehensionExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier parserGenerator = CSharp.Identifier.New("ParserGenerator");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier dictionary = CSharp.Identifier.New("Dictionary");
            CSharp.Identifier keyValuePair = CSharp.Identifier.New("KeyValuePair");
            CSharp.Identifier newDict = CSharp.Identifier.New("New");
            CSharp.Identifier create = CSharp.Identifier.New("Create");
            CSharp.QualifiedAliasMember globalParserGenerator = CSharp.QualifiedAliasMember.New(global, parserGenerator);
            CSharp.Expression globalParserGeneratorCollections = CSharp.Expression.NewQualifiedAliasMemberAccess(globalParserGenerator, collections);
            CSharp.Expression globalParserGeneratorCollectionsDictionary = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollections, dictionary);
            CSharp.Expression globalParserGeneratorCollectionsKeyValuePair = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollections, keyValuePair);
            CSharp.Expression dictionaryNew = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollectionsDictionary, newDict);
            CSharp.Expression keyValuePairCreate = CSharp.Expression.NewObjectMemberAccess(globalParserGeneratorCollectionsKeyValuePair, create);
            Sequence<CSharp.Argument> keyValueItems = Sequence.Create(
                CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(TranslateExpression(n.Key))),
                CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(TranslateExpression(n.Value)))
            );
            CSharp.ArgumentList keyValueArgs = CSharp.ArgumentList.New(keyValueItems);
            CSharp.Expression pair = CSharp.Expression.NewInvocation(keyValuePairCreate, keyValueArgs);
            CSharp.Expression argItem = TranslateComprehension(n.Comprehensions, pair);
            Sequence<CSharp.Argument> argItems = Sequence.Create(CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(argItem)));
            CSharp.ArgumentList argsItems = CSharp.ArgumentList.New(argItems);
            CSharp.Expression call = CSharp.Expression.NewInvocation(dictionaryNew, argsItems);
            return call;
        }

        public virtual CSharp.Expression TranslateIsInstanceOfExpression(IsInstanceOfExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression operand = TranslateExpression(n.Operand);
            CSharp.Type type = TranslateTypeExpression(n.Type);
            return CSharp.Expression.NewIsInstanceOf(operand, type);
        }

        public virtual CSharp.Expression TranslateAsInstanceOfExpression(AsInstanceOfExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression operand = TranslateExpression(n.Operand);
            CSharp.Type type = TranslateTypeExpression(n.Type);
            return CSharp.Expression.NewCast(type, operand);
        }

        public virtual CSharp.Expression TranslateAwaitExpression(AwaitExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression operand = TranslateExpression(n.Operand);
            return CSharp.Expression.NewAwait(operand);
        }

        public virtual CSharp.Expression TranslatePowerExpression(PowerExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression left = TranslateExpression(n.Left);
            CSharp.Expression right = TranslateExpression(n.Right);
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier math = CSharp.Identifier.New("Math");
            CSharp.Identifier pow = CSharp.Identifier.New("Pow");
            CSharp.Argument argLeft = CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(left));
            CSharp.Argument argRight = CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(right));
            CSharp.ArgumentList args = CSharp.ArgumentList.New(Sequence.Create(argLeft, argRight));
            CSharp.QualifiedAliasMember globalSystem = CSharp.QualifiedAliasMember.New(global, system);
            CSharp.Expression globalSystemMath = CSharp.Expression.NewQualifiedAliasMemberAccess(globalSystem, math);
            CSharp.Expression mathPow = CSharp.Expression.NewObjectMemberAccess(globalSystemMath, pow);
            CSharp.Expression call = CSharp.Expression.NewInvocation(mathPow, args);
            return call;
        }

        public virtual CSharp.Expression TranslatePositiveExpression(PositiveExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression operand = TranslateExpression(n.Operand);
            return CSharp.Expression.NewPositive(operand);
        }

        public virtual CSharp.Expression TranslateNegativeExpression(NegativeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression operand = TranslateExpression(n.Operand);
            return CSharp.Expression.NewNegative(operand);
        }

        public virtual CSharp.Expression TranslateBitwiseNotExpression(BitwiseNotExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression operand = TranslateExpression(n.Operand);
            return CSharp.Expression.NewBitwiseNot(operand);
        }

        public virtual CSharp.Expression TranslateLogicalNotExpression(LogicalNotExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression operand = TranslateExpression(n.Operand);
            return CSharp.Expression.NewLogicalNot(operand);
        }

        public virtual CSharp.Expression TranslatePrefixIncrementExpression(PrefixIncrementExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression operand = TranslateExpression(n.Operand);
            return CSharp.Expression.NewPreIncrement(operand);
        }

        public virtual CSharp.Expression TranslatePrefixDecrementExpression(PrefixDecrementExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression operand = TranslateExpression(n.Operand);
            return CSharp.Expression.NewPreDecrement(operand);
        }

        public virtual CSharp.Expression TranslateMultiplyExpression(MultiplyExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression left = TranslateExpression(n.Left);
            CSharp.Expression right = TranslateExpression(n.Right);
            return CSharp.Expression.NewMultiply(left, right);
        }

        public virtual CSharp.Expression TranslateMatrixMultiplyExpression(MatrixMultiplyExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateMatrixMultiply);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Expression TranslateFloorDivideExpression(FloorDivideExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression left = TranslateExpression(n.Left);
            CSharp.Expression right = TranslateExpression(n.Right);
            return CSharp.Expression.NewDivide(left, right);
        }

        public virtual CSharp.Expression TranslateDivideExpression(DivideExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression left = TranslateExpression(n.Left);
            CSharp.Expression right = TranslateExpression(n.Right);
            return CSharp.Expression.NewDivide(left, right);
        }

        public virtual CSharp.Expression TranslateModuloExpression(ModuloExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression left = TranslateExpression(n.Left);
            CSharp.Expression right = TranslateExpression(n.Right);
            return CSharp.Expression.NewModulo(left, right);
        }

        public virtual CSharp.Expression TranslateAddExpression(AddExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression left = TranslateExpression(n.Left);
            CSharp.Expression right = TranslateExpression(n.Right);
            return CSharp.Expression.NewAdd(left, right);
        }

        public virtual CSharp.Expression TranslateSubtractExpression(SubtractExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression left = TranslateExpression(n.Left);
            CSharp.Expression right = TranslateExpression(n.Right);
            return CSharp.Expression.NewSubtract(left, right);
        }

        public virtual CSharp.Expression TranslateLeftShiftExpression(LeftShiftExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression left = TranslateExpression(n.Left);
            CSharp.Expression right = TranslateExpression(n.Right);
            return CSharp.Expression.NewLeftShift(left, right);
        }

        public virtual CSharp.Expression TranslateRightShiftExpression(RightShiftExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression left = TranslateExpression(n.Left);
            CSharp.Expression right = TranslateExpression(n.Right);
            return CSharp.Expression.NewRightShift(left, right);
        }

        public virtual CSharp.Expression TranslateUnsignedRightShiftExpression(UnsignedRightShiftExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression left = TranslateExpression(n.Left);
            CSharp.Expression right = TranslateExpression(n.Right);
            return CSharp.Expression.NewRightShift(left, right);
        }

        public virtual CSharp.Expression TranslateBitwiseAndExpression(BitwiseAndExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression left = TranslateExpression(n.Left);
            CSharp.Expression right = TranslateExpression(n.Right);
            return CSharp.Expression.NewBitwiseAnd(left, right);
        }

        public virtual CSharp.Expression TranslateBitwiseXorExpression(BitwiseXorExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression left = TranslateExpression(n.Left);
            CSharp.Expression right = TranslateExpression(n.Right);
            return CSharp.Expression.NewBitwiseXor(left, right);
        }

        public virtual CSharp.Expression TranslateBitwiseOrExpression(BitwiseOrExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression left = TranslateExpression(n.Left);
            CSharp.Expression right = TranslateExpression(n.Right);
            return CSharp.Expression.NewBitwiseOr(left, right);
        }

        public virtual CSharp.Expression TranslateRelationalExpression(RelationalExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.OpValuePairs.Count == 1)
            {
                RelationalOpValuePair p = n.OpValuePairs[0];
                switch (p.Op)
                {
                    case RelationalOp.EqualTo:
                        return CSharp.Expression.NewEqualTo(TranslateExpression(n.Left), TranslateExpression(p.Value));
                    case RelationalOp.NotEqualTo:
                        return CSharp.Expression.NewNotEqualTo(TranslateExpression(n.Left), TranslateExpression(p.Value));
                    case RelationalOp.LessThan:
                        return CSharp.Expression.NewLessThan(TranslateExpression(n.Left), TranslateExpression(p.Value));
                    case RelationalOp.LessEqual:
                        return CSharp.Expression.NewLessEqual(TranslateExpression(n.Left), TranslateExpression(p.Value));
                    case RelationalOp.GreaterThan:
                        return CSharp.Expression.NewGreaterThan(TranslateExpression(n.Left), TranslateExpression(p.Value));
                    case RelationalOp.GreaterEqual:
                        return CSharp.Expression.NewGreaterEqual(TranslateExpression(n.Left), TranslateExpression(p.Value));
                    case RelationalOp.Is:
                    case RelationalOp.IsNot:
                        if (p.Value.IsNull)
                        {
                            if (p.Op == RelationalOp.Is)
                                return CSharp.Expression.NewEqualTo(TranslateExpression(n.Left), CSharp.Expression.NewLiteral(CSharp.Literal.NewNull()));
                            else
                                return CSharp.Expression.NewNotEqualTo(TranslateExpression(n.Left), CSharp.Expression.NewLiteral(CSharp.Literal.NewNull()));
                        }
                        else
                        {
                            CSharp.Expression left = TranslateExpression(n.Left);
                            CSharp.Expression right = TranslateExpression(p.Value);
                            CSharp.Identifier global = CSharp.Identifier.New("global");
                            CSharp.Identifier system = CSharp.Identifier.New("System");
                            CSharp.Identifier obj = CSharp.Identifier.New("Object");
                            CSharp.Identifier equals = CSharp.Identifier.New("Equals");
                            CSharp.Argument argLeft = CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(left));
                            CSharp.Argument argRight = CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(right));
                            CSharp.ArgumentList args = CSharp.ArgumentList.New(Sequence.Create(argLeft, argRight));
                            CSharp.QualifiedAliasMember globalSystem = CSharp.QualifiedAliasMember.New(global, system);
                            CSharp.Expression globalSystemObject = CSharp.Expression.NewQualifiedAliasMemberAccess(globalSystem, obj);
                            CSharp.Expression objectEquals = CSharp.Expression.NewObjectMemberAccess(globalSystemObject, equals);
                            CSharp.Expression call = CSharp.Expression.NewInvocation(objectEquals, args);
                            if (p.Op == RelationalOp.Is)
                                return call;
                            else
                                return CSharp.Expression.NewLogicalNot(call);
                        }
                    case RelationalOp.In:
                    case RelationalOp.NotIn:
                        {
                            var access = Expression.NewAccess(p.Value, Identifier.New("Contains"));
                            var call = Expression.NewCall(access, ArgumentList.New(Sequence.Create(Argument.NewPositional(n.Left))));
                            var node = call;
                            if (p.Op == RelationalOp.NotIn)
                                node = Expression.NewLogicalNot(node);
                            return TranslateExpression(node);
                        }
                    default:
                        throw new InvalidOperationException(SR.InvalidRelationalOp);
                }
            }
            else
            {
                Expression result = null;
                Expression prev = n.Left;
                foreach (RelationalOpValuePair pair in n.OpValuePairs)
                {
                    Expression cond = Expression.NewRelational(prev, Sequence.Create(pair));
                    if (result == null)
                        result = cond;
                    else
                        result = Expression.NewLogicalAnd(result, cond);
                    prev = pair.Value;
                }
                return TranslateExpression(result);
            }
        }

        public virtual CSharp.Expression TranslateLogicalAndExpression(LogicalAndExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression left = TranslateExpression(n.Left);
            CSharp.Expression right = TranslateExpression(n.Right);
            return CSharp.Expression.NewLogicalAnd(left, right);
        }

        public virtual CSharp.Expression TranslateLogicalOrExpression(LogicalOrExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression left = TranslateExpression(n.Left);
            CSharp.Expression right = TranslateExpression(n.Right);
            return CSharp.Expression.NewLogicalOr(left, right);
        }

        public virtual CSharp.Expression TranslateConditionalExpression(ConditionalExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression test = TranslateExpression(n.Test);
            CSharp.Expression body = TranslateExpression(n.Body);
            CSharp.Expression orElse = TranslateExpression(n.OrElse);
            return CSharp.Expression.NewConditional(test, body, orElse);
        }

        public virtual bool CanBeTranslatedAsAnonymousFunctionSignature(ParameterList n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.PositionalOnly.Count > 0)
                return false;
            if (n.KeywordOnly.Count > 0)
                return false;
            if (n.ExtraPositional != null)
                return false;
            if (n.ExtraKeywords != null)
                return false;
            if (n.Positional.Any(x => x.Value != null))
                return false;
            if (n.Positional.All(x => x.Type == null))
                return true;
            if (n.Positional.All(x => x.Type != null))
                return true;
            return false;
        }

        public virtual CSharp.AnonymousFunctionSignature TranslateAsAnonymousFunctionSignature(ParameterList n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (!CanBeTranslatedAsAnonymousFunctionSignature(n))
            {
                SyntaxErrorException e = new SyntaxErrorException(SR.CanNotBeTranslatedAsAnonymousFunctionSignature);
                e.AddLocation(n.Context);
                throw e;
            }
            if (n.Positional.All(x => x.Type == null))
            {
                if (n.Positional.Count == 0)
                    return CSharp.AnonymousFunctionSignature.NewFullImplicit(null);
                if (n.Positional.Count == 1)
                {
                    var name = CSharp.Identifier.New(n.Positional[0].Name.Name);
                    var parameter = CSharp.ImplicitAnonymousFunctionParameter.New(name);
                    return CSharp.AnonymousFunctionSignature.NewSimpleImplicit(parameter);
                }
                Sequence<CSharp.ImplicitAnonymousFunctionParameter> parameters = n.Positional.Map(
                    x => CSharp.ImplicitAnonymousFunctionParameter.New(
                        CSharp.Identifier.New(x.Name.Name))
                );
                var parameterList = CSharp.ImplicitAnonymousFunctionParameterList.New(parameters);
                return CSharp.AnonymousFunctionSignature.NewFullImplicit(parameterList);
            }
            else
            {
                Sequence<CSharp.ExplicitAnonymousFunctionParameter> parameters = n.Positional.Map(
                    x => CSharp.ExplicitAnonymousFunctionParameter.New(null,
                        TranslateTypeExpression(x.Type),
                        CSharp.Identifier.New(x.Name.Name))
                );
                var parameterList = CSharp.ExplicitAnonymousFunctionParameterList.New(parameters);
                return CSharp.AnonymousFunctionSignature.NewExplicit(parameterList);
            }
        }

        public virtual CSharp.Expression TranslateLambdaExpression(LambdaExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            var signature = TranslateAsAnonymousFunctionSignature(n.Parameters);
            var value = TranslateExpression(n.Body);
            var body = CSharp.AnonymousFunctionBody.NewExpression(value);
            return CSharp.Expression.NewLambda(signature, body);
        }

        public virtual CSharp.Expression TranslateYieldFromExpression(YieldFromExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateYieldFrom);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Expression TranslateYieldExpression(YieldExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateYield);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Expression TranslateYieldBreakExpression(YieldBreakExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateYieldBreak);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Expression TranslateUnpackExpression(UnpackExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateUnpack);
            e.AddLocation(n.Context);
            throw e;
        }
        #endregion

        #region type expressions
        public virtual CSharp.Type TranslateTypeExpression(TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return n.AcceptTypeExpressionTranslator(this);
        }

        public virtual CSharp.Type TranslateInt8TypeExpression(Int8TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewSByte();
        }

        public virtual CSharp.Type TranslateInt16TypeExpression(Int16TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewShort();
        }

        public virtual CSharp.Type TranslateInt32TypeExpression(Int32TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewInt();
        }

        public virtual CSharp.Type TranslateInt64TypeExpression(Int64TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewLong();
        }

        public virtual CSharp.Type TranslateUInt8TypeExpression(UInt8TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewByte();
        }

        public virtual CSharp.Type TranslateUInt16TypeExpression(UInt16TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewUShort();
        }

        public virtual CSharp.Type TranslateUInt32TypeExpression(UInt32TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewUInt();
        }

        public virtual CSharp.Type TranslateUInt64TypeExpression(UInt64TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewULong();
        }

        public virtual CSharp.Type TranslateFloat32TypeExpression(Float32TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewFloat();
        }

        public virtual CSharp.Type TranslateFloat64TypeExpression(Float64TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewDouble();
        }

        public virtual CSharp.Type TranslateChar8TypeExpression(Char8TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewByte();
        }

        public virtual CSharp.Type TranslateChar16TypeExpression(Char16TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewChar();
        }

        public virtual CSharp.Type TranslateChar32TypeExpression(Char32TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewInt();
        }

        public virtual CSharp.Type TranslateSByteTypeExpression(SByteTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewSByte();
        }

        public virtual CSharp.Type TranslateShortTypeExpression(ShortTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewShort();
        }

        public virtual CSharp.Type TranslateIntTypeExpression(IntTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewInt();
        }

        public virtual CSharp.Type TranslateLongTypeExpression(LongTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewLong();
        }

        public virtual CSharp.Type TranslateByteTypeExpression(ByteTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewByte();
        }

        public virtual CSharp.Type TranslateUShortTypeExpression(UShortTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewUShort();
        }

        public virtual CSharp.Type TranslateUIntTypeExpression(UIntTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewUInt();
        }

        public virtual CSharp.Type TranslateULongTypeExpression(ULongTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewULong();
        }

        public virtual CSharp.Type TranslateIntPtrTTypeExpression(IntPtrTTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier intPtr = CSharp.Identifier.New("IntPtr");
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemIntPtr = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, intPtr);
            CSharp.TypeName intPtrTypeName = CSharp.TypeName.New(globalSystemIntPtr);
            CSharp.Type intPtrType = CSharp.Type.NewNamedStruct(intPtrTypeName);
            return intPtrType;
        }

        public virtual CSharp.Type TranslateUIntPtrTTypeExpression(UIntPtrTTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier uintPtr = CSharp.Identifier.New("UIntPtr");
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemUIntPtr = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, uintPtr);
            CSharp.TypeName uintPtrTypeName = CSharp.TypeName.New(globalSystemUIntPtr);
            CSharp.Type uintPtrType = CSharp.Type.NewNamedStruct(uintPtrTypeName);
            return uintPtrType;
        }

        public virtual CSharp.Type TranslateSizeTTypeExpression(SizeTTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier uintPtr = CSharp.Identifier.New("UIntPtr");
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemUIntPtr = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, uintPtr);
            CSharp.TypeName uintPtrTypeName = CSharp.TypeName.New(globalSystemUIntPtr);
            CSharp.Type uintPtrType = CSharp.Type.NewNamedStruct(uintPtrTypeName);
            return uintPtrType;
        }

        public virtual CSharp.Type TranslateSSizeTTypeExpression(SSizeTTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier intPtr = CSharp.Identifier.New("IntPtr");
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemIntPtr = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, intPtr);
            CSharp.TypeName intPtrTypeName = CSharp.TypeName.New(globalSystemIntPtr);
            CSharp.Type intPtrType = CSharp.Type.NewNamedStruct(intPtrTypeName);
            return intPtrType;
        }

        public virtual CSharp.Type TranslatePtrDiffTTypeExpression(PtrDiffTTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier intPtr = CSharp.Identifier.New("IntPtr");
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemIntPtr = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, intPtr);
            CSharp.TypeName intPtrTypeName = CSharp.TypeName.New(globalSystemIntPtr);
            CSharp.Type intPtrType = CSharp.Type.NewNamedStruct(intPtrTypeName);
            return intPtrType;
        }

        public virtual CSharp.Type TranslateFloatTypeExpression(FloatTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewFloat();
        }

        public virtual CSharp.Type TranslateDoubleTypeExpression(DoubleTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewDouble();
        }

        public virtual CSharp.Type TranslateDecimalTypeExpression(DecimalTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewDecimal();
        }

        public virtual CSharp.Type TranslateBoolTypeExpression(BoolTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewBool();
        }

        public virtual CSharp.Type TranslateCharTypeExpression(CharTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewChar();
        }

        public virtual CSharp.Type TranslateStringTypeExpression(StringTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewString();
        }

        public virtual CSharp.Type TranslateObjectTypeExpression(ObjectTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewObject();
        }

        public virtual CSharp.Type TranslateDynamicTypeExpression(DynamicTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewDynamic();
        }

        public virtual CSharp.Type TranslateUnitTypeExpression(UnitTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewObject();
        }

        public virtual CSharp.Type TranslateTupleTypeExpression(TupleTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            List<CSharp.Type> list = new List<CSharp.Type>();
            foreach (TypeExpression t in n.ElementTypes)
            {
                CSharp.Type item = TranslateTypeExpression(t);
                list.Add(item);
            }
            bool first = true;
            while (true)
            {
                int num = 8;
                if (first)
                {
                    first = false;
                    num = list.Count % 7;
                    if (num == 0)
                        num = 7;
                }
                Sequence<CSharp.Type> items = Sequence.New(list.GetRange(list.Count - num, num));
                Sequence<CSharp.TypeArgument> argItems = items.Map(t => CSharp.TypeArgument.New(t));
                list.RemoveRange(list.Count - num, num);
                CSharp.Identifier global = CSharp.Identifier.New("global");
                CSharp.Identifier system = CSharp.Identifier.New("System");
                CSharp.Identifier tuple = CSharp.Identifier.New("Tuple");
                CSharp.TypeArgumentList typeArgs = CSharp.TypeArgumentList.New(CSharp.TypeArguments.New(argItems));
                CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
                CSharp.NamespaceOrTypeName globalSystemTuple = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, tuple, typeArgs);
                CSharp.TypeName tupleTypeName = CSharp.TypeName.New(globalSystemTuple);
                CSharp.Type tupleType = CSharp.Type.NewNamedClass(tupleTypeName);
                if (list.Count == 0)
                    return tupleType;
                list.Add(tupleType);
            }
        }

        public virtual CSharp.Type TranslateRecordTypeExpression(RecordTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateRecordType);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Type TranslateValueTupleTypeExpression(ValueTupleTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            List<CSharp.Type> list = new List<CSharp.Type>();
            foreach (TypeExpression t in n.ElementTypes)
            {
                CSharp.Type item = TranslateTypeExpression(t);
                list.Add(item);
            }
            bool first = true;
            while (true)
            {
                int num = 8;
                if (first)
                {
                    first = false;
                    num = list.Count % 7;
                    if (num == 0)
                        num = 7;
                }
                Sequence<CSharp.Type> items = Sequence.New(list.GetRange(list.Count - num, num));
                Sequence<CSharp.TypeArgument> argItems = items.Map(t => CSharp.TypeArgument.New(t));
                list.RemoveRange(list.Count - num, num);
                CSharp.Identifier global = CSharp.Identifier.New("global");
                CSharp.Identifier system = CSharp.Identifier.New("System");
                CSharp.Identifier valueTuple = CSharp.Identifier.New("ValueTuple");
                CSharp.TypeArgumentList typeArgs = CSharp.TypeArgumentList.New(CSharp.TypeArguments.New(argItems));
                CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
                CSharp.NamespaceOrTypeName globalSystemValueTuple = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, valueTuple, typeArgs);
                CSharp.TypeName valueTupleTypeName = CSharp.TypeName.New(globalSystemValueTuple);
                CSharp.Type valueTupleType = CSharp.Type.NewNamedClass(valueTupleTypeName);
                if (list.Count == 0)
                    return valueTupleType;
                list.Add(valueTupleType);
            }
        }

        public virtual CSharp.Type TranslateValueRecordTypeExpression(ValueRecordTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateValueRecordType);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Type TranslateListTypeExpression(ListTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier objectModel = CSharp.Identifier.New("ObjectModel");
            CSharp.Identifier readOnlyCollection = CSharp.Identifier.New("ReadOnlyCollection");
            CSharp.Type elementType = TranslateTypeExpression(n.ElementType);
            CSharp.TypeArgumentList typeArgs = CSharp.TypeArgumentList.New(CSharp.TypeArguments.New(Sequence.Create(CSharp.TypeArgument.New(elementType))));
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemCollections = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, collections);
            CSharp.NamespaceOrTypeName globalSystemCollectionsObjectModel = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollections, objectModel);
            CSharp.NamespaceOrTypeName globalSystemCollectionsObjectModelReadOnlyCollection = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollectionsObjectModel, readOnlyCollection, typeArgs);
            CSharp.TypeName readOnlyCollectionTypeName = CSharp.TypeName.New(globalSystemCollectionsObjectModelReadOnlyCollection);
            CSharp.Type readOnlyCollectionType = CSharp.Type.NewNamedClass(readOnlyCollectionTypeName);
            return readOnlyCollectionType;
        }

        public virtual CSharp.Type TranslateSetTypeExpression(SetTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier parserGenerator = CSharp.Identifier.New("ParserGenerator");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier readOnlySet = CSharp.Identifier.New("ReadOnlySet");
            CSharp.Type elementType = TranslateTypeExpression(n.ElementType);
            CSharp.TypeArgumentList typeArgs = CSharp.TypeArgumentList.New(CSharp.TypeArguments.New(Sequence.Create(CSharp.TypeArgument.New(elementType))));
            CSharp.NamespaceOrTypeName globalParserGenerator = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, parserGenerator));
            CSharp.NamespaceOrTypeName globalParserGeneratorCollections = CSharp.NamespaceOrTypeName.NewQualified(globalParserGenerator, collections);
            CSharp.NamespaceOrTypeName globalParserGeneratorCollectionsReadOnlySet = CSharp.NamespaceOrTypeName.NewQualified(globalParserGeneratorCollections, readOnlySet, typeArgs);
            CSharp.TypeName readOnlySetTypeName = CSharp.TypeName.New(globalParserGeneratorCollectionsReadOnlySet);
            CSharp.Type readOnlySetType = CSharp.Type.NewNamedClass(readOnlySetTypeName);
            return readOnlySetType;
        }

        public virtual CSharp.Type TranslateMapTypeExpression(MapTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier objectModel = CSharp.Identifier.New("ObjectModel");
            CSharp.Identifier readOnlyDictionary = CSharp.Identifier.New("ReadOnlyDictionary");
            CSharp.Type keyType = TranslateTypeExpression(n.KeyType);
            CSharp.Type valueType = TranslateTypeExpression(n.ValueType);
            CSharp.TypeArgumentList typeArgs = CSharp.TypeArgumentList.New(CSharp.TypeArguments.New(Sequence.Create(CSharp.TypeArgument.New(keyType), CSharp.TypeArgument.New(valueType))));
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemCollections = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, collections);
            CSharp.NamespaceOrTypeName globalSystemCollectionsObjectModel = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollections, objectModel);
            CSharp.NamespaceOrTypeName globalSystemCollectionsObjectModelReadOnlyDictionary = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollectionsObjectModel, readOnlyDictionary, typeArgs);
            CSharp.TypeName readOnlyDictionaryTypeName = CSharp.TypeName.New(globalSystemCollectionsObjectModelReadOnlyDictionary);
            CSharp.Type readOnlyDictionaryType = CSharp.Type.NewNamedClass(readOnlyDictionaryTypeName);
            return readOnlyDictionaryType;
        }

        public virtual CSharp.NamespaceOrTypeName TranslateTypeName(TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            switch (n.Tag)
            {
                case TypeExpressionCategory.NameReference:
                    {
                        CSharp.Identifier name = CSharp.Identifier.New(n.AsNameReference.Name.Name);
                        return CSharp.NamespaceOrTypeName.NewUnqualified(name);
                    }
                case TypeExpressionCategory.GlobalNameReference:
                    {
                        CSharp.Identifier scope = CSharp.Identifier.New("global");
                        CSharp.Identifier member = CSharp.Identifier.New(n.AsGlobalNameReference.Name.Name);
                        CSharp.QualifiedAliasMember qmember = CSharp.QualifiedAliasMember.New(scope, member);
                        return CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(qmember);
                    }
                case TypeExpressionCategory.Access:
                    {
                        CSharp.NamespaceOrTypeName scope = TranslateTypeName(n.AsAccess.Operand);
                        CSharp.Identifier member = CSharp.Identifier.New(n.AsAccess.Member.Name);
                        return CSharp.NamespaceOrTypeName.NewQualified(scope, member);
                    }
                case TypeExpressionCategory.BoundedGeneric:
                    if (n.AsBoundedGeneric.Operand.IsNameReference)
                    {
                        CSharp.Identifier name = CSharp.Identifier.New(n.AsBoundedGeneric.Operand.AsNameReference.Name.Name);
                        CSharp.TypeArguments types = CSharp.TypeArguments.New(n.AsBoundedGeneric.Arguments.Map(t => CSharp.TypeArgument.New(TranslateTypeExpression(t))));
                        CSharp.TypeArgumentList argTypes = CSharp.TypeArgumentList.New(types);
                        return CSharp.NamespaceOrTypeName.NewUnqualified(name, argTypes);
                    }
                    else if (n.AsBoundedGeneric.Operand.IsGlobalNameReference)
                    {
                        CSharp.Identifier scope = CSharp.Identifier.New("global");
                        CSharp.Identifier member = CSharp.Identifier.New(n.AsBoundedGeneric.Operand.AsGlobalNameReference.Name.Name);
                        CSharp.TypeArguments types = CSharp.TypeArguments.New(n.AsBoundedGeneric.Arguments.Map(t => CSharp.TypeArgument.New(TranslateTypeExpression(t))));
                        CSharp.TypeArgumentList argTypes = CSharp.TypeArgumentList.New(types);
                        CSharp.QualifiedAliasMember qmember = CSharp.QualifiedAliasMember.New(scope, member, argTypes);
                        return CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(qmember);
                    }
                    else if (n.AsBoundedGeneric.Operand.IsAccess)
                    {
                        CSharp.NamespaceOrTypeName operand = TranslateTypeName(n.AsBoundedGeneric.Operand.AsAccess.Operand);
                        CSharp.Identifier name = CSharp.Identifier.New(n.AsBoundedGeneric.Operand.AsAccess.Member.Name);
                        CSharp.TypeArguments types = CSharp.TypeArguments.New(n.AsBoundedGeneric.Arguments.Map(t => CSharp.TypeArgument.New(TranslateTypeExpression(t))));
                        CSharp.TypeArgumentList argTypes = CSharp.TypeArgumentList.New(types);
                        return CSharp.NamespaceOrTypeName.NewQualified(operand, name, argTypes);
                    }
                    else
                    {
                        SyntaxErrorException e = new SyntaxErrorException(SR.TypeArgumentsAppliedToWrongOperand);
                        e.AddLocation(n.AsBoundedGeneric.Operand.Context);
                        throw e;
                    }
                default:
                    {
                        SyntaxErrorException e = new SyntaxErrorException(SR.CanNotBeTranslatedAsTypeName);
                        e.AddLocation(n.Context);
                        throw e;
                    }
            }
        }

        public virtual CSharp.UnboundTypeName TranslateUnboundTypeName(TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            switch (n.Tag)
            {
                case TypeExpressionCategory.NameReference:
                    {
                        CSharp.Identifier name = CSharp.Identifier.New(n.AsNameReference.Name.Name);
                        return CSharp.UnboundTypeName.NewUnqualified(name);
                    }
                case TypeExpressionCategory.GlobalNameReference:
                    {
                        CSharp.Identifier scope = CSharp.Identifier.New("global");
                        CSharp.Identifier member = CSharp.Identifier.New(n.AsGlobalNameReference.Name.Name);
                        CSharp.UnboundQualifiedAliasMember qmember = CSharp.UnboundQualifiedAliasMember.New(scope, member);
                        return CSharp.UnboundTypeName.NewQualifiedAliasMember(qmember);
                    }
                case TypeExpressionCategory.Access:
                    {
                        CSharp.UnboundTypeName scope = TranslateUnboundTypeName(n.AsAccess.Operand);
                        CSharp.Identifier member = CSharp.Identifier.New(n.AsAccess.Member.Name);
                        return CSharp.UnboundTypeName.NewQualified(scope, member);
                    }
                case TypeExpressionCategory.UnboundedGeneric:
                    if (n.AsUnboundedGeneric.Operand.IsNameReference)
                    {
                        CSharp.Identifier name = CSharp.Identifier.New(n.AsUnboundedGeneric.Operand.AsNameReference.Name.Name);
                        CSharp.GenericDimensionSpecifier specifier = CSharp.GenericDimensionSpecifier.New(n.AsUnboundedGeneric.Arity);
                        return CSharp.UnboundTypeName.NewUnqualified(name, specifier);
                    }
                    else if (n.AsUnboundedGeneric.Operand.IsGlobalNameReference)
                    {
                        CSharp.Identifier scope = CSharp.Identifier.New("global");
                        CSharp.Identifier member = CSharp.Identifier.New(n.AsUnboundedGeneric.Operand.AsGlobalNameReference.Name.Name);
                        CSharp.GenericDimensionSpecifier specifier = CSharp.GenericDimensionSpecifier.New(n.AsUnboundedGeneric.Arity);
                        CSharp.UnboundQualifiedAliasMember qmember = CSharp.UnboundQualifiedAliasMember.New(scope, member, specifier);
                        return CSharp.UnboundTypeName.NewQualifiedAliasMember(qmember);
                    }
                    else if (n.AsUnboundedGeneric.Operand.IsAccess)
                    {
                        CSharp.UnboundTypeName operand = TranslateUnboundTypeName(n.AsUnboundedGeneric.Operand.AsAccess.Operand);
                        CSharp.Identifier name = CSharp.Identifier.New(n.AsUnboundedGeneric.Operand.AsAccess.Member.Name);
                        CSharp.GenericDimensionSpecifier specifier = CSharp.GenericDimensionSpecifier.New(n.AsUnboundedGeneric.Arity);
                        return CSharp.UnboundTypeName.NewQualified(operand, name, specifier);
                    }
                    else
                    {
                        SyntaxErrorException e = new SyntaxErrorException(SR.GenericDimensionSpecifierAppliedToWrongOperand);
                        e.AddLocation(n.AsUnboundedGeneric.Operand.Context);
                        throw e;
                    }
                default:
                    {
                        SyntaxErrorException e = new SyntaxErrorException(SR.CanNotBeTranslatedAsUnboundTypeName);
                        e.AddLocation(n.Context);
                        throw e;
                    }
            }
        }

        public virtual CSharp.Type TranslateNameReferenceTypeExpression(NameReferenceTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewNamedClass(CSharp.TypeName.New(TranslateTypeName(n)));
        }

        public virtual CSharp.Type TranslateGlobalNameReferenceTypeExpression(GlobalNameReferenceTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewNamedClass(CSharp.TypeName.New(TranslateTypeName(n)));
        }

        public virtual CSharp.Type TranslateAccessTypeExpression(AccessTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewNamedClass(CSharp.TypeName.New(TranslateTypeName(n)));
        }

        public virtual CSharp.Type TranslateUnboundedGenericTypeExpression(UnboundedGenericTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotBeTranslatedAsTypeName);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Type TranslateBoundedGenericTypeExpression(BoundedGenericTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewNamedClass(CSharp.TypeName.New(TranslateTypeName(n)));
        }

        public virtual CSharp.Type TranslateNonNegativeInt8TypeExpression(NonNegativeInt8TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewSByte();
        }

        public virtual CSharp.Type TranslateNonNegativeInt16TypeExpression(NonNegativeInt16TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewShort();
        }

        public virtual CSharp.Type TranslateNonNegativeInt32TypeExpression(NonNegativeInt32TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewInt();
        }

        public virtual CSharp.Type TranslateNonNegativeInt64TypeExpression(NonNegativeInt64TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewLong();
        }

        public virtual CSharp.Type TranslateNonNegativeFloat32TypeExpression(NonNegativeFloat32TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewFloat();
        }

        public virtual CSharp.Type TranslateNonNegativeFloat64TypeExpression(NonNegativeFloat64TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewDouble();
        }

        public virtual CSharp.Type TranslateNonNegativeSByteTypeExpression(NonNegativeSByteTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewSByte();
        }

        public virtual CSharp.Type TranslateNonNegativeShortTypeExpression(NonNegativeShortTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewShort();
        }

        public virtual CSharp.Type TranslateNonNegativeIntTypeExpression(NonNegativeIntTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewInt();
        }

        public virtual CSharp.Type TranslateNonNegativeLongTypeExpression(NonNegativeLongTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewLong();
        }

        public virtual CSharp.Type TranslateNonNegativeIntPtrTTypeExpression(NonNegativeIntPtrTTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier intPtr = CSharp.Identifier.New("IntPtr");
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemIntPtr = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, intPtr);
            CSharp.TypeName intPtrTypeName = CSharp.TypeName.New(globalSystemIntPtr);
            CSharp.Type intPtrType = CSharp.Type.NewNamedStruct(intPtrTypeName);
            return intPtrType;
        }

        public virtual CSharp.Type TranslateNonNegativeSSizeTTypeExpression(NonNegativeSSizeTTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier intPtr = CSharp.Identifier.New("IntPtr");
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemIntPtr = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, intPtr);
            CSharp.TypeName intPtrTypeName = CSharp.TypeName.New(globalSystemIntPtr);
            CSharp.Type intPtrType = CSharp.Type.NewNamedStruct(intPtrTypeName);
            return intPtrType;
        }

        public virtual CSharp.Type TranslateNonNegativePtrDiffTTypeExpression(NonNegativePtrDiffTTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier intPtr = CSharp.Identifier.New("IntPtr");
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemIntPtr = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, intPtr);
            CSharp.TypeName intPtrTypeName = CSharp.TypeName.New(globalSystemIntPtr);
            CSharp.Type intPtrType = CSharp.Type.NewNamedStruct(intPtrTypeName);
            return intPtrType;
        }

        public virtual CSharp.Type TranslateNonNegativeFloatTypeExpression(NonNegativeFloatTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewFloat();
        }

        public virtual CSharp.Type TranslateNonNegativeDoubleTypeExpression(NonNegativeDoubleTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewDouble();
        }

        public virtual CSharp.Type TranslateNonNegativeDecimalTypeExpression(NonNegativeDecimalTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewDecimal();
        }

        public virtual CSharp.Type TranslatePositiveInt8TypeExpression(PositiveInt8TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewSByte();
        }

        public virtual CSharp.Type TranslatePositiveInt16TypeExpression(PositiveInt16TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewShort();
        }

        public virtual CSharp.Type TranslatePositiveInt32TypeExpression(PositiveInt32TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewInt();
        }

        public virtual CSharp.Type TranslatePositiveInt64TypeExpression(PositiveInt64TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewLong();
        }

        public virtual CSharp.Type TranslatePositiveFloat32TypeExpression(PositiveFloat32TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewFloat();
        }

        public virtual CSharp.Type TranslatePositiveFloat64TypeExpression(PositiveFloat64TypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewDouble();
        }

        public virtual CSharp.Type TranslatePositiveSByteTypeExpression(PositiveSByteTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewSByte();
        }

        public virtual CSharp.Type TranslatePositiveShortTypeExpression(PositiveShortTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewShort();
        }

        public virtual CSharp.Type TranslatePositiveIntTypeExpression(PositiveIntTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewInt();
        }

        public virtual CSharp.Type TranslatePositiveLongTypeExpression(PositiveLongTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewLong();
        }

        public virtual CSharp.Type TranslatePositiveIntPtrTTypeExpression(PositiveIntPtrTTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier intPtr = CSharp.Identifier.New("IntPtr");
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemIntPtr = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, intPtr);
            CSharp.TypeName intPtrTypeName = CSharp.TypeName.New(globalSystemIntPtr);
            CSharp.Type intPtrType = CSharp.Type.NewNamedStruct(intPtrTypeName);
            return intPtrType;
        }

        public virtual CSharp.Type TranslatePositiveSSizeTTypeExpression(PositiveSSizeTTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier intPtr = CSharp.Identifier.New("IntPtr");
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemIntPtr = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, intPtr);
            CSharp.TypeName intPtrTypeName = CSharp.TypeName.New(globalSystemIntPtr);
            CSharp.Type intPtrType = CSharp.Type.NewNamedStruct(intPtrTypeName);
            return intPtrType;
        }

        public virtual CSharp.Type TranslatePositiveDiffTTypeExpression(PositiveDiffTTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier intPtr = CSharp.Identifier.New("IntPtr");
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemIntPtr = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, intPtr);
            CSharp.TypeName intPtrTypeName = CSharp.TypeName.New(globalSystemIntPtr);
            CSharp.Type intPtrType = CSharp.Type.NewNamedStruct(intPtrTypeName);
            return intPtrType;
        }

        public virtual CSharp.Type TranslatePositiveFloatTypeExpression(PositiveFloatTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewFloat();
        }

        public virtual CSharp.Type TranslatePositiveDoubleTypeExpression(PositiveDoubleTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewDouble();
        }

        public virtual CSharp.Type TranslatePositiveDecimalTypeExpression(PositiveDecimalTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Type.NewDecimal();
        }

        public virtual CSharp.Type TranslateMutableListTypeExpression(MutableListTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier generic = CSharp.Identifier.New("Generic");
            CSharp.Identifier list = CSharp.Identifier.New("List");
            CSharp.Type elementType = TranslateTypeExpression(n.ElementType);
            CSharp.TypeArgumentList typeArgs = CSharp.TypeArgumentList.New(CSharp.TypeArguments.New(Sequence.Create(CSharp.TypeArgument.New(elementType))));
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemCollections = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, collections);
            CSharp.NamespaceOrTypeName globalSystemCollectionsGeneric = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollections, generic);
            CSharp.NamespaceOrTypeName globalSystemCollectionsGenericList = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollectionsGeneric, list, typeArgs);
            CSharp.TypeName listTypeName = CSharp.TypeName.New(globalSystemCollectionsGenericList);
            CSharp.Type listType = CSharp.Type.NewNamedClass(listTypeName);
            return listType;
        }

        public virtual CSharp.Type TranslateMutableSetTypeExpression(MutableSetTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier generic = CSharp.Identifier.New("Generic");
            CSharp.Identifier hashSet = CSharp.Identifier.New("HashSet");
            CSharp.Type elementType = TranslateTypeExpression(n.ElementType);
            CSharp.TypeArgumentList typeArgs = CSharp.TypeArgumentList.New(CSharp.TypeArguments.New(Sequence.Create(CSharp.TypeArgument.New(elementType))));
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemCollections = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, collections);
            CSharp.NamespaceOrTypeName globalSystemCollectionsGeneric = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollections, generic);
            CSharp.NamespaceOrTypeName globalSystemCollectionsGenericHashSet = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollectionsGeneric, hashSet, typeArgs);
            CSharp.TypeName hashSetTypeName = CSharp.TypeName.New(globalSystemCollectionsGenericHashSet);
            CSharp.Type hashSetType = CSharp.Type.NewNamedClass(hashSetTypeName);
            return hashSetType;
        }

        public virtual CSharp.Type TranslateMutableMapTypeExpression(MutableMapTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier generic = CSharp.Identifier.New("Generic");
            CSharp.Identifier dictionary = CSharp.Identifier.New("Dictionary");
            CSharp.Type keyType = TranslateTypeExpression(n.KeyType);
            CSharp.Type valueType = TranslateTypeExpression(n.ValueType);
            CSharp.TypeArgumentList typeArgs = CSharp.TypeArgumentList.New(CSharp.TypeArguments.New(Sequence.Create(CSharp.TypeArgument.New(keyType), CSharp.TypeArgument.New(valueType))));
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemCollections = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, collections);
            CSharp.NamespaceOrTypeName globalSystemCollectionsGeneric = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollections, generic);
            CSharp.NamespaceOrTypeName globalSystemCollectionsGenericDictionary = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollectionsGeneric, dictionary, typeArgs);
            CSharp.TypeName dictionaryTypeName = CSharp.TypeName.New(globalSystemCollectionsGenericDictionary);
            CSharp.Type dictionaryType = CSharp.Type.NewNamedClass(dictionaryTypeName);
            return dictionaryType;
        }

        public virtual CSharp.Type TranslateNonEmptyListTypeExpression(NonEmptyListTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier objectModel = CSharp.Identifier.New("ObjectModel");
            CSharp.Identifier readOnlyCollection = CSharp.Identifier.New("ReadOnlyCollection");
            CSharp.Type elementType = TranslateTypeExpression(n.ElementType);
            CSharp.TypeArgumentList typeArgs = CSharp.TypeArgumentList.New(CSharp.TypeArguments.New(Sequence.Create(CSharp.TypeArgument.New(elementType))));
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemCollections = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, collections);
            CSharp.NamespaceOrTypeName globalSystemCollectionsObjectModel = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollections, objectModel);
            CSharp.NamespaceOrTypeName globalSystemCollectionsObjectModelReadOnlyCollection = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollectionsObjectModel, readOnlyCollection, typeArgs);
            CSharp.TypeName readOnlyCollectionTypeName = CSharp.TypeName.New(globalSystemCollectionsObjectModelReadOnlyCollection);
            CSharp.Type readOnlyCollectionType = CSharp.Type.NewNamedClass(readOnlyCollectionTypeName);
            return readOnlyCollectionType;
        }

        public virtual CSharp.Type TranslateNonEmptySetTypeExpression(NonEmptySetTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier parserGenerator = CSharp.Identifier.New("ParserGenerator");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier readOnlySet = CSharp.Identifier.New("ReadOnlySet");
            CSharp.Type elementType = TranslateTypeExpression(n.ElementType);
            CSharp.TypeArgumentList typeArgs = CSharp.TypeArgumentList.New(CSharp.TypeArguments.New(Sequence.Create(CSharp.TypeArgument.New(elementType))));
            CSharp.NamespaceOrTypeName globalParserGenerator = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, parserGenerator));
            CSharp.NamespaceOrTypeName globalParserGeneratorCollections = CSharp.NamespaceOrTypeName.NewQualified(globalParserGenerator, collections);
            CSharp.NamespaceOrTypeName globalParserGeneratorCollectionsReadOnlySet = CSharp.NamespaceOrTypeName.NewQualified(globalParserGeneratorCollections, readOnlySet, typeArgs);
            CSharp.TypeName readOnlySetTypeName = CSharp.TypeName.New(globalParserGeneratorCollectionsReadOnlySet);
            CSharp.Type readOnlySetType = CSharp.Type.NewNamedClass(readOnlySetTypeName);
            return readOnlySetType;
        }

        public virtual CSharp.Type TranslateNonEmptyMapTypeExpression(NonEmptyMapTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier objectModel = CSharp.Identifier.New("ObjectModel");
            CSharp.Identifier readOnlyDictionary = CSharp.Identifier.New("ReadOnlyDictionary");
            CSharp.Type keyType = TranslateTypeExpression(n.KeyType);
            CSharp.Type valueType = TranslateTypeExpression(n.ValueType);
            CSharp.TypeArgumentList typeArgs = CSharp.TypeArgumentList.New(CSharp.TypeArguments.New(Sequence.Create(CSharp.TypeArgument.New(keyType), CSharp.TypeArgument.New(valueType))));
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemCollections = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, collections);
            CSharp.NamespaceOrTypeName globalSystemCollectionsObjectModel = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollections, objectModel);
            CSharp.NamespaceOrTypeName globalSystemCollectionsObjectModelReadOnlyDictionary = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollectionsObjectModel, readOnlyDictionary, typeArgs);
            CSharp.TypeName readOnlyDictionaryTypeName = CSharp.TypeName.New(globalSystemCollectionsObjectModelReadOnlyDictionary);
            CSharp.Type readOnlyDictionaryType = CSharp.Type.NewNamedClass(readOnlyDictionaryTypeName);
            return readOnlyDictionaryType;
        }

        public virtual CSharp.Type TranslateNonEmptyMutableListTypeExpression(NonEmptyMutableListTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier generic = CSharp.Identifier.New("Generic");
            CSharp.Identifier list = CSharp.Identifier.New("List");
            CSharp.Type elementType = TranslateTypeExpression(n.ElementType);
            CSharp.TypeArgumentList typeArgs = CSharp.TypeArgumentList.New(CSharp.TypeArguments.New(Sequence.Create(CSharp.TypeArgument.New(elementType))));
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemCollections = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, collections);
            CSharp.NamespaceOrTypeName globalSystemCollectionsGeneric = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollections, generic);
            CSharp.NamespaceOrTypeName globalSystemCollectionsGenericList = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollectionsGeneric, list, typeArgs);
            CSharp.TypeName listTypeName = CSharp.TypeName.New(globalSystemCollectionsGenericList);
            CSharp.Type listType = CSharp.Type.NewNamedClass(listTypeName);
            return listType;
        }

        public virtual CSharp.Type TranslateNonEmptyMutableSetTypeExpression(NonEmptyMutableSetTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier generic = CSharp.Identifier.New("Generic");
            CSharp.Identifier hashSet = CSharp.Identifier.New("HashSet");
            CSharp.Type elementType = TranslateTypeExpression(n.ElementType);
            CSharp.TypeArgumentList typeArgs = CSharp.TypeArgumentList.New(CSharp.TypeArguments.New(Sequence.Create(CSharp.TypeArgument.New(elementType))));
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemCollections = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, collections);
            CSharp.NamespaceOrTypeName globalSystemCollectionsGeneric = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollections, generic);
            CSharp.NamespaceOrTypeName globalSystemCollectionsGenericHashSet = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollectionsGeneric, hashSet, typeArgs);
            CSharp.TypeName hashSetTypeName = CSharp.TypeName.New(globalSystemCollectionsGenericHashSet);
            CSharp.Type hashSetType = CSharp.Type.NewNamedClass(hashSetTypeName);
            return hashSetType;
        }

        public virtual CSharp.Type TranslateNonEmptyMutableMapTypeExpression(NonEmptyMutableMapTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier collections = CSharp.Identifier.New("Collections");
            CSharp.Identifier generic = CSharp.Identifier.New("Generic");
            CSharp.Identifier dictionary = CSharp.Identifier.New("Dictionary");
            CSharp.Type keyType = TranslateTypeExpression(n.KeyType);
            CSharp.Type valueType = TranslateTypeExpression(n.ValueType);
            CSharp.TypeArgumentList typeArgs = CSharp.TypeArgumentList.New(CSharp.TypeArguments.New(Sequence.Create(CSharp.TypeArgument.New(keyType), CSharp.TypeArgument.New(valueType))));
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemCollections = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, collections);
            CSharp.NamespaceOrTypeName globalSystemCollectionsGeneric = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollections, generic);
            CSharp.NamespaceOrTypeName globalSystemCollectionsGenericDictionary = CSharp.NamespaceOrTypeName.NewQualified(globalSystemCollectionsGeneric, dictionary, typeArgs);
            CSharp.TypeName dictionaryTypeName = CSharp.TypeName.New(globalSystemCollectionsGenericDictionary);
            CSharp.Type dictionaryType = CSharp.Type.NewNamedClass(dictionaryTypeName);
            return dictionaryType;
        }

        public virtual CSharp.Type TranslateNullableTypeExpression(NullableTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Type operand = TranslateTypeExpression(n.OperandType);
            return CSharp.Type.NewNullable(CSharp.NonNullableValueType.New(operand));
        }

        public virtual CSharp.Type TranslateUnionTypeExpression(UnionTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateUnionType);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Type TranslateFunctionTypeExpression(FunctionTypeExpression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            List<CSharp.Type> list = new List<CSharp.Type>();
            list.Add(TranslateTypeExpression(n.ArgumentType));
            TypeExpression p = n.ResultType;
            while (p.IsFunction)
            {
                list.Add(TranslateTypeExpression(p.AsFunction.ArgumentType));
                p = p.AsFunction.ResultType;
            }
            if (list.Count > 16)
            {
                SyntaxErrorException e = new SyntaxErrorException(SR.TooManyArgumentTypes);
                e.AddLocation(n.Context);
                throw e;
            }
            if (!p.IsUnit)
                list.Add(TranslateTypeExpression(p));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier actionOrFunc = CSharp.Identifier.New(p.IsUnit ? "Action" : "Func");
            Sequence<CSharp.TypeArgument> argsList = Sequence.New(list.Select(t => CSharp.TypeArgument.New(t)));
            CSharp.TypeArgumentList typeArgs = CSharp.TypeArgumentList.New(CSharp.TypeArguments.New(argsList));
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemActionOrFunc = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, actionOrFunc, typeArgs);
            CSharp.TypeName actionOrFuncTypeName = CSharp.TypeName.New(globalSystemActionOrFunc);
            CSharp.Type actionOrFuncType = CSharp.Type.NewNamedClass(actionOrFuncTypeName);
            return actionOrFuncType;
        }
        #endregion

        #region statements
        public virtual CSharp.Statement TranslateStatement(Statement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return n.AcceptStatementTranslator(this);
        }

        public virtual CSharp.Statement TranslatePassStatement(PassStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Statement.NewEmpty();
        }

        public virtual CSharp.Statement TranslateBreakStatement(BreakStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Statement.NewBreak();
        }

        public virtual CSharp.Statement TranslateContinueStatement(ContinueStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return CSharp.Statement.NewContinue();
        }

        public virtual CSharp.Statement TranslateReturnStatement(ReturnStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.Value == null)
                return CSharp.Statement.NewReturn();
            CSharp.Expression value = TranslateExpression(n.Value);
            return CSharp.Statement.NewReturn(value);
        }

        public virtual CSharp.Statement TranslateThrowStatement(ThrowStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.Exception == null)
                return CSharp.Statement.NewThrow();
            CSharp.Expression exception = TranslateExpression(n.Exception);
            if (n.Cause == null)
                return CSharp.Statement.NewThrow(exception);
            if (exception.IsObjectCreation)
            {
                CSharp.ObjectCreationExpression newExpr = exception.AsObjectCreation;
                if (newExpr.Initializer == null && newExpr.Arguments != null && newExpr.Arguments.Items.Count == 1)
                {
                    CSharp.Expression innerExc = TranslateExpression(n.Cause);
                    CSharp.ArgumentValue innerExcArgValue = CSharp.ArgumentValue.NewIn(innerExc);
                    CSharp.Argument innerExcArg = CSharp.Argument.New(null, innerExcArgValue);
                    Sequence<CSharp.Argument> newArgItems = Sequence.Append(newExpr.Arguments.Items, innerExcArg);
                    CSharp.ArgumentList newArgList = newExpr.Arguments.WithItems(newArgItems);
                    CSharp.Expression newException = newExpr.WithArguments(newArgList);
                    return CSharp.Statement.NewThrow(newException);
                }
            }
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier aggregateException = CSharp.Identifier.New("AggregateException");
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemAggregateException = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, aggregateException);
            CSharp.TypeName aggregateExceptionTypeName = CSharp.TypeName.New(globalSystemAggregateException);
            CSharp.Type aggregateExceptionType = CSharp.Type.NewNamedClass(aggregateExceptionTypeName);
            CSharp.Expression innerException = TranslateExpression(n.Cause);
            CSharp.ArgumentValue exceptionArgVal = CSharp.ArgumentValue.NewIn(exception);
            CSharp.ArgumentValue innerExceptionArgVal = CSharp.ArgumentValue.NewIn(innerException);
            CSharp.Argument exceptionArg = CSharp.Argument.New(null, exceptionArgVal);
            CSharp.Argument innerExceptionArg = CSharp.Argument.New(null, innerExceptionArgVal);
            Sequence<CSharp.Argument> argItems = Sequence.Create(exceptionArg, innerExceptionArg);
            CSharp.ArgumentList argList = CSharp.ArgumentList.New(argItems);
            CSharp.Expression newExc = CSharp.Expression.NewObjectCreation(aggregateExceptionType, argList);
            return CSharp.Statement.NewThrow(newExc);
        }

        public virtual CSharp.Statement TranslateAssertStatement(AssertStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier diagnostics = CSharp.Identifier.New("Diagnostics");
            CSharp.Identifier debug = CSharp.Identifier.New("Debug");
            CSharp.Identifier assert = CSharp.Identifier.New("Assert");
            CSharp.Expression condition = TranslateExpression(n.Test);
            Sequence<CSharp.Argument> argItems = Sequence.Create(CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(condition)));
            if (n.Message != null)
            {
                CSharp.Expression message = TranslateExpression(n.Message);
                argItems = Sequence.Append(argItems, CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(message)));
            }
            CSharp.ArgumentList argList = CSharp.ArgumentList.New(argItems);
            CSharp.QualifiedAliasMember globalSystem = CSharp.QualifiedAliasMember.New(global, system);
            CSharp.Expression globalSystemDiagnostics = CSharp.Expression.NewQualifiedAliasMemberAccess(globalSystem, diagnostics);
            CSharp.Expression globalSystemDiagnosticsDebug = CSharp.Expression.NewObjectMemberAccess(globalSystemDiagnostics, debug);
            CSharp.Expression debugAssert = CSharp.Expression.NewObjectMemberAccess(globalSystemDiagnosticsDebug, assert);
            CSharp.Expression call = CSharp.Expression.NewInvocation(debugAssert, argList);
            CSharp.StatementExpression expr = CSharp.StatementExpression.New(call);
            return CSharp.Statement.NewExpression(expr);
        }

        public virtual CSharp.UnaryExpression TranslateTargetExpression(Expression n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression target = TranslateExpression(n);
            if (!target.IsUnary)
            {
                SyntaxErrorException e = new SyntaxErrorException(SR.TargetExpressionCanNotBeTranslateAsUnaryCSharpExpression);
                e.AddLocation(n.Context);
                throw e;
            }
            return target.AsUnary;
        }

        public virtual CSharp.Statement TranslateDeleteStatement(DeleteStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.Targets.Count == 1)
            {
                CSharp.UnaryExpression target = TranslateTargetExpression(n.Targets[0]);
                CSharp.Expression value = CSharp.Expression.NewLiteral(CSharp.Literal.NewNull());
                CSharp.Expression assign = CSharp.Expression.NewAssignment(target, CSharp.AssignmentOperator.NewAssign(), value);
                CSharp.StatementExpression expr = CSharp.StatementExpression.New(assign);
                return CSharp.Statement.NewExpression(expr);
            }
            else
            {
                Sequence<CSharp.Statement> items = Sequence.GetEmpty<CSharp.Statement>();
                foreach (Expression targetExpression in n.Targets)
                {
                    CSharp.UnaryExpression target = TranslateTargetExpression(targetExpression);
                    CSharp.Expression value = CSharp.Expression.NewLiteral(CSharp.Literal.NewNull());
                    CSharp.Expression assign = CSharp.Expression.NewAssignment(target, CSharp.AssignmentOperator.NewAssign(), value);
                    CSharp.StatementExpression expr = CSharp.StatementExpression.New(assign);
                    CSharp.Statement item = CSharp.Statement.NewExpression(expr);
                    items = Sequence.Append(items, item);
                }
                CSharp.StatementList statements = CSharp.StatementList.New(items);
                CSharp.Block block = CSharp.Block.New(statements);
                return CSharp.Statement.NewBlock(block);
            }
        }

        public virtual CSharp.Statement TranslateGlobalStatement(GlobalStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateGlobal);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Statement TranslateNonlocalStatement(NonlocalStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateNonlocal);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Statement TranslateImportStatement(ImportStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateImport);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Statement TranslateFromImportStatement(FromImportStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateFromImport);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Statement TranslateFromImportAllStatement(FromImportAllStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateFromImportAll);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Statement TranslateLetStatement(LetStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier name = CSharp.Identifier.New(n.Variable.Name);
            CSharp.LocalVariableType type;
            if (n.Type == null)
                type = CSharp.LocalVariableType.NewVar();
            else
                type = CSharp.LocalVariableType.NewSpecific(TranslateTypeExpression(n.Type));
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.LocalVariableInitializer initializer = CSharp.LocalVariableInitializer.NewSingle(value);
            CSharp.LocalVariableDeclarator declarator = CSharp.LocalVariableDeclarator.New(name, initializer);
            CSharp.LocalVariableDeclarators declarators = CSharp.LocalVariableDeclarators.New(Sequence.Create(declarator));
            CSharp.LocalVariableDeclaration declaration = CSharp.LocalVariableDeclaration.New(type, declarators);
            return CSharp.Statement.NewLocalVariableDeclaration(declaration);
        }

        public virtual CSharp.Statement TranslateVarStatement(VarStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Identifier name = CSharp.Identifier.New(n.Variable.Name);
            CSharp.LocalVariableType type;
            if (n.Type == null)
                type = CSharp.LocalVariableType.NewVar();
            else
                type = CSharp.LocalVariableType.NewSpecific(TranslateTypeExpression(n.Type));
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.LocalVariableInitializer initializer = CSharp.LocalVariableInitializer.NewSingle(value);
            CSharp.LocalVariableDeclarator declarator = CSharp.LocalVariableDeclarator.New(name, initializer);
            CSharp.LocalVariableDeclarators declarators = CSharp.LocalVariableDeclarators.New(Sequence.Create(declarator));
            CSharp.LocalVariableDeclaration declaration = CSharp.LocalVariableDeclaration.New(type, declarators);
            return CSharp.Statement.NewLocalVariableDeclaration(declaration);
        }

        public virtual CSharp.Statement TranslateConstStatement(ConstStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.Type == null)
            {
                CSharp.Identifier name = CSharp.Identifier.New(n.Variable.Name);
                CSharp.LocalVariableType type = CSharp.LocalVariableType.NewVar();
                CSharp.Expression value = TranslateExpression(n.Value);
                CSharp.LocalVariableInitializer initializer = CSharp.LocalVariableInitializer.NewSingle(value);
                CSharp.LocalVariableDeclarator declarator = CSharp.LocalVariableDeclarator.New(name, initializer);
                CSharp.LocalVariableDeclarators declarators = CSharp.LocalVariableDeclarators.New(Sequence.Create(declarator));
                CSharp.LocalVariableDeclaration declaration = CSharp.LocalVariableDeclaration.New(type, declarators);
                return CSharp.Statement.NewLocalVariableDeclaration(declaration);
            }
            else
            {
                CSharp.Identifier name = CSharp.Identifier.New(n.Variable.Name);
                CSharp.Type type = TranslateTypeExpression(n.Type);
                CSharp.ConstantExpression value = CSharp.ConstantExpression.New(TranslateExpression(n.Value));
                CSharp.ConstantDeclarator declarator = CSharp.ConstantDeclarator.New(name, value);
                CSharp.ConstantDeclarators declarators = CSharp.ConstantDeclarators.New(Sequence.Create(declarator));
                CSharp.LocalConstantDeclaration declaration = CSharp.LocalConstantDeclaration.New(type, declarators);
                return CSharp.Statement.NewLocalConstantDeclaration(declaration);
            }
        }

        public virtual CSharp.Identifier SynthesizeIdentifier(string prefix, SourceContext context)
        {
            if (prefix == null)
                throw new ArgumentNullException(nameof(prefix));
            if (context == null)
                throw new ArgumentNullException(nameof(context));
            int x = ICollectionExtensions.GetItemHashCode(context.Document.FullName);
            int y = ICollectionExtensions.GetItemHashCode(context.Begin.Index);
            int h = ICollectionExtensions.CombineHashCodes(x, y);
            string name = prefix + Math.Abs(h);
            return CSharp.Identifier.New(name);
        }

        public virtual CSharp.Statement TranslateExprStatement(ExprStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.Value.IsYieldFrom)
            {
                var node = n.Value.AsYieldFrom;
                CSharp.Identifier enumerator = SynthesizeIdentifier("t", node.Context);
                CSharp.Expression enumerable = TranslateExpression(node.Value);
                CSharp.Expression enumeratorRef = CSharp.Expression.NewSimpleName(CSharp.SimpleName.New(enumerator));
                CSharp.Statement yieldReturnValue = CSharp.Statement.NewYieldReturn(enumeratorRef);
                CSharp.CompoundStatementBody foreachBody = WrapAsCompoundStatementBody(yieldReturnValue);
                CSharp.LocalVariableType enumeratorType = CSharp.LocalVariableType.NewVar();
                return CSharp.Statement.NewForEach(enumeratorType, enumerator, enumerable, foreachBody);
            }
            if (n.Value.IsYield && n.Value.AsYield.Value != null)
                return CSharp.Statement.NewYieldReturn(TranslateExpression(n.Value.AsYield.Value));
            if (n.Value.IsYieldBreak)
                return CSharp.Statement.NewYieldBreak();
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.StatementExpression expr = CSharp.StatementExpression.New(value);
            return CSharp.Statement.NewExpression(expr);
        }

        public virtual CSharp.Statement TranslateAssignStatement(AssignStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Expression value = TranslateExpression(n.Value);
            for (int i = n.Targets.Count - 1; i >= 0; i--)
            {
                CSharp.UnaryExpression target = TranslateTargetExpression(n.Targets[i]);
                value = CSharp.Expression.NewAssignment(target, CSharp.AssignmentOperator.NewAssign(), value);
            }
            CSharp.StatementExpression expr = CSharp.StatementExpression.New(value);
            return CSharp.Statement.NewExpression(expr);
        }

        public virtual CSharp.Statement TranslateAnnotatedAssignStatement(AnnotatedAssignStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (!n.IsSingle)
            {
                SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateAnnotatedAssignWithComplexTargets);
                e.AddLocation(n.Context);
                throw e;
            }
            CSharp.Identifier name = CSharp.Identifier.New(n.Target.AsNameReference.Name.Name);
            CSharp.Type t = TranslateTypeExpression(n.Type);
            CSharp.LocalVariableType type = CSharp.LocalVariableType.NewSpecific(t);
            CSharp.Expression value = n.Value != null ? TranslateExpression(n.Value) : CSharp.Expression.NewDefaultValue(t);
            CSharp.LocalVariableInitializer initializer = CSharp.LocalVariableInitializer.NewSingle(value);
            CSharp.LocalVariableDeclarator declarator = CSharp.LocalVariableDeclarator.New(name, initializer);
            CSharp.LocalVariableDeclarators declarators = CSharp.LocalVariableDeclarators.New(Sequence.Create(declarator));
            CSharp.LocalVariableDeclaration declaration = CSharp.LocalVariableDeclaration.New(type, declarators);
            return CSharp.Statement.NewLocalVariableDeclaration(declaration);
        }

        public virtual CSharp.Statement TranslateAddAssignStatement(AddAssignStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.UnaryExpression target = TranslateTargetExpression(n.Target);
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.Expression assign = CSharp.Expression.NewAssignment(target, CSharp.AssignmentOperator.NewAddAssign(), value);
            CSharp.StatementExpression expr = CSharp.StatementExpression.New(assign);
            return CSharp.Statement.NewExpression(expr);
        }

        public virtual CSharp.Statement TranslateSubtractAssignStatement(SubtractAssignStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.UnaryExpression target = TranslateTargetExpression(n.Target);
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.Expression assign = CSharp.Expression.NewAssignment(target, CSharp.AssignmentOperator.NewSubtractAssign(), value);
            CSharp.StatementExpression expr = CSharp.StatementExpression.New(assign);
            return CSharp.Statement.NewExpression(expr);
        }

        public virtual CSharp.Statement TranslateMultiplyAssignStatement(MultiplyAssignStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.UnaryExpression target = TranslateTargetExpression(n.Target);
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.Expression assign = CSharp.Expression.NewAssignment(target, CSharp.AssignmentOperator.NewMultiplyAssign(), value);
            CSharp.StatementExpression expr = CSharp.StatementExpression.New(assign);
            return CSharp.Statement.NewExpression(expr);
        }

        public virtual CSharp.Statement TranslateMatrixMultiplyAssignStatement(MatrixMultiplyAssignStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateMatrixMultiplyAssign);
            e.AddLocation(n.Context);
            throw e;
        }

        public virtual CSharp.Statement TranslateFloorDivideAssignStatement(FloorDivideAssignStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.UnaryExpression target = TranslateTargetExpression(n.Target);
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.Expression assign = CSharp.Expression.NewAssignment(target, CSharp.AssignmentOperator.NewDivideAssign(), value);
            CSharp.StatementExpression expr = CSharp.StatementExpression.New(assign);
            return CSharp.Statement.NewExpression(expr);
        }

        public virtual CSharp.Statement TranslateDivideAssignStatement(DivideAssignStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.UnaryExpression target = TranslateTargetExpression(n.Target);
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.Expression assign = CSharp.Expression.NewAssignment(target, CSharp.AssignmentOperator.NewDivideAssign(), value);
            CSharp.StatementExpression expr = CSharp.StatementExpression.New(assign);
            return CSharp.Statement.NewExpression(expr);
        }

        public virtual CSharp.Statement TranslateModuloAssignStatement(ModuloAssignStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.UnaryExpression target = TranslateTargetExpression(n.Target);
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.Expression assign = CSharp.Expression.NewAssignment(target, CSharp.AssignmentOperator.NewModuloAssign(), value);
            CSharp.StatementExpression expr = CSharp.StatementExpression.New(assign);
            return CSharp.Statement.NewExpression(expr);
        }

        public virtual CSharp.Statement TranslatePowerAssignStatement(PowerAssignStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.UnaryExpression target = TranslateTargetExpression(n.Target);
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier math = CSharp.Identifier.New("Math");
            CSharp.Identifier pow = CSharp.Identifier.New("Pow");
            CSharp.Argument argLeft = CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(target));
            CSharp.Argument argRight = CSharp.Argument.New(null, CSharp.ArgumentValue.NewIn(value));
            CSharp.ArgumentList args = CSharp.ArgumentList.New(Sequence.Create(argLeft, argRight));
            CSharp.QualifiedAliasMember globalSystem = CSharp.QualifiedAliasMember.New(global, system);
            CSharp.Expression globalSystemMath = CSharp.Expression.NewQualifiedAliasMemberAccess(globalSystem, math);
            CSharp.Expression mathPow = CSharp.Expression.NewObjectMemberAccess(globalSystemMath, pow);
            CSharp.Expression call = CSharp.Expression.NewInvocation(mathPow, args);
            CSharp.Expression assign = CSharp.Expression.NewAssignment(target, CSharp.AssignmentOperator.NewAssign(), call);
            CSharp.StatementExpression expr = CSharp.StatementExpression.New(assign);
            return CSharp.Statement.NewExpression(expr);
        }

        public virtual CSharp.Statement TranslateLeftShiftAssignStatement(LeftShiftAssignStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.UnaryExpression target = TranslateTargetExpression(n.Target);
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.Expression assign = CSharp.Expression.NewAssignment(target, CSharp.AssignmentOperator.NewLeftShiftAssign(), value);
            CSharp.StatementExpression expr = CSharp.StatementExpression.New(assign);
            return CSharp.Statement.NewExpression(expr);
        }

        public virtual CSharp.Statement TranslateRightShiftAssignStatement(RightShiftAssignStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.UnaryExpression target = TranslateTargetExpression(n.Target);
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.Expression assign = CSharp.Expression.NewAssignment(target, CSharp.AssignmentOperator.NewRightShiftAssign(), value);
            CSharp.StatementExpression expr = CSharp.StatementExpression.New(assign);
            return CSharp.Statement.NewExpression(expr);
        }

        public virtual CSharp.Statement TranslateUnsignedRightShiftAssignStatement(UnsignedRightShiftAssignStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.UnaryExpression target = TranslateTargetExpression(n.Target);
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.Expression assign = CSharp.Expression.NewAssignment(target, CSharp.AssignmentOperator.NewRightShiftAssign(), value);
            CSharp.StatementExpression expr = CSharp.StatementExpression.New(assign);
            return CSharp.Statement.NewExpression(expr);
        }

        public virtual CSharp.Statement TranslateBitwiseAndAssignStatement(BitwiseAndAssignStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.UnaryExpression target = TranslateTargetExpression(n.Target);
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.Expression assign = CSharp.Expression.NewAssignment(target, CSharp.AssignmentOperator.NewBitwiseAndAssign(), value);
            CSharp.StatementExpression expr = CSharp.StatementExpression.New(assign);
            return CSharp.Statement.NewExpression(expr);
        }

        public virtual CSharp.Statement TranslateBitwiseXorAssignStatement(BitwiseXorAssignStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.UnaryExpression target = TranslateTargetExpression(n.Target);
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.Expression assign = CSharp.Expression.NewAssignment(target, CSharp.AssignmentOperator.NewBitwiseXorAssign(), value);
            CSharp.StatementExpression expr = CSharp.StatementExpression.New(assign);
            return CSharp.Statement.NewExpression(expr);
        }

        public virtual CSharp.Statement TranslateBitwiseOrAssignStatement(BitwiseOrAssignStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.UnaryExpression target = TranslateTargetExpression(n.Target);
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.Expression assign = CSharp.Expression.NewAssignment(target, CSharp.AssignmentOperator.NewBitwiseAndAssign(), value);
            CSharp.StatementExpression expr = CSharp.StatementExpression.New(assign);
            return CSharp.Statement.NewExpression(expr);
        }

        public virtual CSharp.Statement TranslateSequenceStatement(SequenceStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.Items.Count == 1)
                return TranslateStatement(n.Items[0]);
            Sequence<CSharp.Statement> items = Sequence.GetEmpty<CSharp.Statement>();
            foreach (Statement statement in n.Items)
            {
                CSharp.Statement item = TranslateStatement(statement);
                items = Sequence.Append(items, item);
            }
            CSharp.StatementList statements = CSharp.StatementList.New(items);
            CSharp.Block block = CSharp.Block.New(statements);
            return CSharp.Statement.NewBlock(block);
        }

        public virtual CSharp.Statement TranslateSimpleStatement(SimpleStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return TranslateStatement(n.Body);
        }

        public virtual CSharp.Statement TranslateBlockStatement(BlockStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            Sequence<CSharp.Statement> items = Sequence.GetEmpty<CSharp.Statement>();
            foreach (Statement statement in n.Body)
            {
                CSharp.Statement item = TranslateStatement(statement);
                items = Sequence.Append(items, item);
            }
            CSharp.StatementList statements = CSharp.StatementList.New(items);
            CSharp.Block block = CSharp.Block.New(statements);
            return CSharp.Statement.NewBlock(block);
        }

        public virtual CSharp.Statement TranslateSuiteStatement(SuiteStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return TranslateStatement(n.Body);
        }

        public virtual CSharp.Block ExtractOrWrapAsBlock(CSharp.Statement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.IsBlock)
                return n.AsBlock.Block;
            if (n.IsEmpty)
                return CSharp.Block.New(null);
            Sequence<CSharp.Statement> items = Sequence.Create(n);
            CSharp.StatementList statements = CSharp.StatementList.New(items);
            CSharp.Block block = CSharp.Block.New(statements);
            return block;
        }

        public virtual Sequence<CSharp.Statement> ExtractOrWrapAsStatementList(CSharp.Statement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.IsEmpty)
                return Sequence.GetEmpty<CSharp.Statement>();
            if (!n.IsBlock)
                return Sequence.Create(n);
            CSharp.Block block = n.AsBlock.Block;
            if (block.Statements == null)
                return Sequence.GetEmpty<CSharp.Statement>();
            if (block.Statements.Items.Count == 1)
                return ExtractOrWrapAsStatementList(block.Statements.Items[0]);
            return block.Statements.Items;
        }

        public virtual CSharp.CompoundStatementBody WrapAsCompoundStatementBody(CSharp.Statement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Block block = ExtractOrWrapAsBlock(n);
            CSharp.Statement body = CSharp.Statement.NewBlock(block);
            return CSharp.CompoundStatementBody.New(body.AsEmbedded);
        }

        public virtual CSharp.CompoundStatementBody TranslateCompoundStatementBody(Statement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Statement item = TranslateStatement(n);
            return WrapAsCompoundStatementBody(item);
        }

        public virtual CSharp.Block TranslateExceptionHandlerBlock(Statement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Statement item = TranslateStatement(n);
            return ExtractOrWrapAsBlock(item);
        }

        public virtual Sequence<CSharp.Statement> TranslateSwitchSectionStatementList(Statement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Statement item = TranslateStatement(n);
            return ExtractOrWrapAsStatementList(item);
        }

        public virtual CSharp.Statement TranslateWithStatement(WithStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.IsAsync)
            {
                SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateAsyncWithStatement);
                e.AddLocation(n.Context);
                throw e;
            }
            CSharp.Statement result = null;
            CSharp.CompoundStatementBody body = TranslateCompoundStatementBody(n.Body);
            for (int i = n.Bindings.Count - 1; i >= 0; i--)
            {
                WithBinding binding = n.Bindings[i];
                CSharp.Expression value = TranslateExpression(binding.Value);
                CSharp.ResourceAcquisition acquire;
                if (binding.Variables == null)
                    acquire = CSharp.ResourceAcquisition.NewExpression(value);
                else
                {
                    if (!binding.Variables.IsNameReference)
                    {
                        SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateWithStatementWithComplexTargets);
                        e.AddLocation(n.Context);
                        throw e;
                    }
                    CSharp.Identifier name = CSharp.Identifier.New(binding.Variables.AsNameReference.Name.Name);
                    CSharp.LocalVariableType type = CSharp.LocalVariableType.NewVar();
                    CSharp.LocalVariableInitializer initializer = CSharp.LocalVariableInitializer.NewSingle(value);
                    CSharp.LocalVariableDeclarator declarator = CSharp.LocalVariableDeclarator.New(name, initializer);
                    CSharp.LocalVariableDeclarators declarators = CSharp.LocalVariableDeclarators.New(Sequence.Create(declarator));
                    CSharp.LocalVariableDeclaration declaration = CSharp.LocalVariableDeclaration.New(type, declarators);
                    acquire = CSharp.ResourceAcquisition.NewDeclaration(declaration);
                }
                if (result != null)
                    body = CSharp.CompoundStatementBody.New(result.AsEmbedded);
                result = CSharp.Statement.NewUsing(acquire, body);
            }
            return result;
        }

        public virtual CSharp.Statement TranslateForStatement(ForStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.IsAsync)
            {
                SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateAsyncForStatement);
                e.AddLocation(n.Context);
                throw e;
            }
            if (!n.Enumerator.IsNameReference)
            {
                SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateForStatementWithComplexTargets);
                e.AddLocation(n.Context);
                throw e;
            }
            if (n.OrElse != null)
            {
                SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateForElse);
                e.AddLocation(n.Context);
                throw e;
            }
            CSharp.LocalVariableType type = CSharp.LocalVariableType.NewVar();
            CSharp.Identifier enumerator = CSharp.Identifier.New(n.Enumerator.AsNameReference.Name.Name);
            CSharp.Expression enumerable = TranslateExpression(n.Enumerable);
            CSharp.CompoundStatementBody body = TranslateCompoundStatementBody(n.Body);
            return CSharp.Statement.NewForEach(type, enumerator, enumerable, body);
        }

        public virtual CSharp.Statement TranslateWhileStatement(WhileStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.OrElse != null)
            {
                SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateWhileElse);
                e.AddLocation(n.Context);
                throw e;
            }
            CSharp.Expression test = TranslateExpression(n.Test);
            CSharp.BooleanExpression condition = CSharp.BooleanExpression.New(test);
            CSharp.CompoundStatementBody body = TranslateCompoundStatementBody(n.Body);
            return CSharp.Statement.NewWhile(condition, body);
        }

        public virtual CSharp.Statement TranslateIfStatement(IfStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Statement result = null;
            for (int i = n.ElseIfBranches.Count - 1; i >= 0; i--)
            {
                ElseIfBranch branch = n.ElseIfBranches[i];
                CSharp.Expression elifTest = TranslateExpression(branch.Test);
                CSharp.BooleanExpression elifCondition = CSharp.BooleanExpression.New(elifTest);
                CSharp.CompoundStatementBody elifBody = TranslateCompoundStatementBody(branch.Body);
                CSharp.CompoundStatementBody elifOrElseBody;
                if (result != null)
                    elifOrElseBody = WrapAsCompoundStatementBody(result);
                else if (n.OrElse != null)
                    elifOrElseBody = TranslateCompoundStatementBody(n.OrElse);
                else
                    elifOrElseBody = null;
                result = CSharp.Statement.NewIf(elifCondition, elifBody, elifOrElseBody);
            }
            CSharp.Expression test = TranslateExpression(n.Test);
            CSharp.BooleanExpression condition = CSharp.BooleanExpression.New(test);
            CSharp.CompoundStatementBody body = TranslateCompoundStatementBody(n.Body);
            CSharp.CompoundStatementBody orElseBody;
            if (result != null)
                orElseBody = WrapAsCompoundStatementBody(result);
            else if (n.OrElse != null)
                orElseBody = TranslateCompoundStatementBody(n.OrElse);
            else
                orElseBody = null;
            return CSharp.Statement.NewIf(condition, body, orElseBody);
        }

        public virtual CSharp.Statement TranslateTryStatement(TryStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.OrElse != null)
            {
                SyntaxErrorException e = new SyntaxErrorException(SR.CanNotTranslateTryElse);
                e.AddLocation(n.Context);
                throw e;
            }
            Sequence<CSharp.SpecificCatchClause> clauses = Sequence.GetEmpty<CSharp.SpecificCatchClause>();
            CSharp.GeneralCatchClause generalCatchClause = null;
            for (int i = 0; i < n.Handlers.Count; i++)
            {
                ExceptionHandler handler = n.Handlers[i];
                if (i == n.Handlers.Count - 1 && handler.Type == null)
                {
                    CSharp.Block clauseBody = TranslateExceptionHandlerBlock(handler.Body);
                    generalCatchClause = CSharp.GeneralCatchClause.New(clauseBody);
                }
                else
                {
                    CSharp.Type type;
                    if (handler.Type != null)
                        type = TranslateTypeExpression(handler.Type);
                    else
                    {
                        CSharp.Identifier global = CSharp.Identifier.New("global");
                        CSharp.Identifier system = CSharp.Identifier.New("System");
                        CSharp.Identifier exception = CSharp.Identifier.New("Exception");
                        CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
                        CSharp.NamespaceOrTypeName globalSystemException = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, exception);
                        CSharp.TypeName exceptionTypeName = CSharp.TypeName.New(globalSystemException);
                        type = CSharp.Type.NewNamedClass(exceptionTypeName);
                    }
                    CSharp.Identifier name = null;
                    if (handler.Name != null)
                        name = CSharp.Identifier.New(handler.Name.Name);
                    CSharp.Block clauseBody = TranslateExceptionHandlerBlock(handler.Body);
                    CSharp.SpecificCatchClause clause = CSharp.SpecificCatchClause.New(type, name, clauseBody);
                    clauses = Sequence.Append(clauses, clause);
                }
            }
            CSharp.SpecificCatchClauses specificCatchClauses = null;
            if (clauses.Count > 0)
                specificCatchClauses = CSharp.SpecificCatchClauses.New(clauses);
            CSharp.CatchClauseList catchClauseList;
            if (generalCatchClause != null)
                catchClauseList = CSharp.CatchClauseList.NewWithGeneral(specificCatchClauses, generalCatchClause);
            else if (specificCatchClauses != null)
                catchClauseList = CSharp.CatchClauseList.NewAllSpecific(specificCatchClauses);
            else
                catchClauseList = null;
            CSharp.Block body = TranslateExceptionHandlerBlock(n.Body);
            if (n.FinalBody == null)
                return CSharp.Statement.NewTry(body, catchClauseList);
            CSharp.Block finallyBody = TranslateExceptionHandlerBlock(n.FinalBody);
            CSharp.FinallyClause finallyClause = CSharp.FinallyClause.New(finallyBody);
            return CSharp.Statement.NewTryWithFinally(body, catchClauseList, finallyClause);
        }

        public virtual CSharp.Statement TranslateSwitchStatement(SwitchStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            Sequence<CSharp.SwitchSection> switchSections = Sequence.GetEmpty<CSharp.SwitchSection>();
            Sequence<CSharp.SwitchLabel> switchLabels = Sequence.GetEmpty<CSharp.SwitchLabel>();
            foreach (SwitchCaseClause item in n.Clauses)
            {
                CSharp.Expression value = TranslateExpression(item.Value);
                CSharp.ConstantExpression caseValue = CSharp.ConstantExpression.New(value);
                CSharp.SwitchLabel label = CSharp.SwitchLabel.NewCase(caseValue);
                switchLabels = Sequence.Append(switchLabels, label);
                Sequence<CSharp.Statement> statements = TranslateSwitchSectionStatementList(item.Body);
                if (statements.Count > 0)
                {
                    CSharp.SwitchLabels sectionLabels = CSharp.SwitchLabels.New(switchLabels);
                    CSharp.StatementList sectionStatements = CSharp.StatementList.New(statements);
                    CSharp.SwitchSection switchSection = CSharp.SwitchSection.New(sectionLabels, sectionStatements);
                    switchSections = Sequence.Append(switchSections, switchSection);
                    switchLabels = Sequence.GetEmpty<CSharp.SwitchLabel>();
                }
            }
            Sequence<CSharp.Statement> defaultStatements = Sequence.GetEmpty<CSharp.Statement>();
            if (n.DefaultActions != null)
            {
                Sequence<CSharp.Statement> statements = TranslateSwitchSectionStatementList(n.DefaultActions);
                if (statements.Count > 0)
                {
                    CSharp.SwitchLabel label = CSharp.SwitchLabel.NewDefault();
                    switchLabels = Sequence.Append(switchLabels, label);
                    defaultStatements = statements;
                }
            }
            if (switchLabels.Count > 0)
            {
                if (defaultStatements.Count == 0)
                {
                    CSharp.Statement empty = CSharp.Statement.NewEmpty();
                    defaultStatements = Sequence.Append(defaultStatements, empty);
                }
                CSharp.SwitchLabels defaultSectionLabels = CSharp.SwitchLabels.New(switchLabels);
                CSharp.StatementList defaultSectionStatements = CSharp.StatementList.New(defaultStatements);
                CSharp.SwitchSection defaultSection = CSharp.SwitchSection.New(defaultSectionLabels, defaultSectionStatements);
                switchSections = Sequence.Append(switchSections, defaultSection);
            }
            CSharp.SwitchSections sections = null;
            if (switchSections.Count > 0)
                sections = CSharp.SwitchSections.New(switchSections);
            CSharp.SwitchBlock switchBlock = CSharp.SwitchBlock.New(sections);
            CSharp.Expression switchValue = TranslateExpression(n.Value);
            return CSharp.Statement.NewSwitch(switchValue, switchBlock);
        }

        public virtual CSharp.Statement TranslateFunctionStatement(FunctionStatement n)
        {
            // TODO
            throw new NotImplementedException();
        }

        public virtual CSharp.Statement TranslateClassStatement(ClassStatement n)
        {
            // TODO
            throw new NotImplementedException();
        }

        public virtual CSharp.Statement TranslateGrammarStatement(GrammarStatement n)
        {
            // TODO
            throw new NotImplementedException();
        }

        public virtual CSharp.Statement TranslateEnumTypeStatement(EnumTypeStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.EnumDeclaration enumDeclaration = TranslateEnumDeclarator(n.Declarator);
            Console.WriteLine(enumDeclaration);
            return null;
            // TODO
            throw new NotImplementedException();
        }

        public virtual CSharp.Statement TranslateStructTypeStatement(StructTypeStatement n)
        {
            // TODO
            throw new NotImplementedException();
        }

        public virtual CSharp.Statement TranslateUnionTypeStatement(UnionTypeStatement n)
        {
            // TODO
            throw new NotImplementedException();
        }

        public virtual CSharp.Statement TranslateVisitorTypeStatement(VisitorTypeStatement n)
        {
            // TODO
            throw new NotImplementedException();
        }

        public virtual CSharp.Statement TranslateInterfaceTypeStatement(InterfaceTypeStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.InterfaceDeclaration interfaceDeclaration = TranslateInterfaceDeclarator(n.Declarator);
            Console.WriteLine(interfaceDeclaration);
            return null;
            // TODO
            throw new NotImplementedException();
        }

        public virtual CSharp.Statement TranslateClassTypeStatement(ClassTypeStatement n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.TypeDeclaration typeDeclaration = TranslateClassDeclarator(n.Declarator);
            Console.WriteLine(typeDeclaration);
            return null;
            // TODO
            throw new NotImplementedException();
        }
        #endregion

        #region type declarator
        public virtual CSharp.Attribute GetSerializableAttribute()
        {
            CSharp.Identifier global = CSharp.Identifier.New("global");
            CSharp.Identifier system = CSharp.Identifier.New("System");
            CSharp.Identifier serializable = CSharp.Identifier.New("Serializable");
            CSharp.NamespaceOrTypeName globalSystem = CSharp.NamespaceOrTypeName.NewQualifiedAliasMember(CSharp.QualifiedAliasMember.New(global, system));
            CSharp.NamespaceOrTypeName globalSystemSerializable = CSharp.NamespaceOrTypeName.NewQualified(globalSystem, serializable);
            CSharp.TypeName serializableTypeName = CSharp.TypeName.New(globalSystemSerializable);
            CSharp.AttributeName serializableAttributeName = CSharp.AttributeName.New(serializableTypeName);
            return CSharp.Attribute.New(serializableAttributeName);
        }

        public virtual CSharp.Attributes GetCommonTypeAttributes()
        {
            CSharp.Attribute serializable = GetSerializableAttribute();
            CSharp.AttributeList attributes = CSharp.AttributeList.New(Sequence.Create(serializable));
            CSharp.AttributeSection section = CSharp.AttributeSection.New(null, attributes);
            CSharp.AttributeSections sections = CSharp.AttributeSections.New(Sequence.Create(section));
            return CSharp.Attributes.New(sections);
        }

        public virtual Sequence<CSharp.ClassModifier> TranslateClassVirtualModifierAsClassModifiers(ClassVirtualModifier n)
        {
            switch (n)
            {
                case ClassVirtualModifier.Default:
                    return Sequence.GetEmpty<CSharp.ClassModifier>();
                case ClassVirtualModifier.Sealed:
                    return Sequence.Create(CSharp.ClassModifier.NewSealed());
                case ClassVirtualModifier.Abstract:
                    return Sequence.Create(CSharp.ClassModifier.NewAbstract());
                case ClassVirtualModifier.Static:
                    return Sequence.Create(CSharp.ClassModifier.NewStatic());
                case ClassVirtualModifier.Struct:
                    return Sequence.GetEmpty<CSharp.ClassModifier>();
                default:
                    throw new ArgumentException(SR.InvalidClassVirtualModifier, nameof(n));
            }
        }

        public virtual bool CanBeTranslatedAsFormalParameterList(ParameterList n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.PositionalOnly.Count > 0)
                return false;
            if (n.KeywordOnly.Count > 0)
                return false;
            if (n.ExtraKeywords != null)
                return false;
            if (n.Positional.Any(x => x.Type == null))
                return false;
            if (n.ExtraPositional != null)
            {
                if (n.ExtraPositional.Type == null || n.ExtraPositional.Value != null || !n.ExtraPositional.Type.IsList)
                    return false;
            }
            return true;
        }

        public virtual CSharp.FormalParameterList TranslateAsFormalParameterList(ParameterList n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (!CanBeTranslatedAsFormalParameterList(n))
            {
                SyntaxErrorException e = new SyntaxErrorException(SR.CanNotBeTranslatedAsFormalParameterList);
                e.AddLocation(n.Context);
                throw e;
            }
            if (n.Positional.Count == 0 && n.ExtraKeywords == null)
                return null;
            Sequence<CSharp.FixedParameter> parameters = n.Positional.Map(
                x => CSharp.FixedParameter.New(null, null,
                    TranslateTypeExpression(x.Type),
                    CSharp.Identifier.New(x.Name.Name),
                    x.Value != null ? CSharp.DefaultArgument.New(TranslateExpression(x.Value)) : null)
            );
            CSharp.FixedParameters fixedParameters = null;
            if (parameters.Count > 0)
                fixedParameters = CSharp.FixedParameters.New(parameters);
            CSharp.ParameterArray paramArray = null;
            if (n.ExtraPositional != null)
            {
                paramArray = CSharp.ParameterArray.New(null,
                    CSharp.ArrayType.New(
                        CSharp.NonArrayType.New(TranslateTypeExpression(n.ExtraPositional.Type.AsList.ElementType)),
                        CSharp.RankSpecifiers.New(Sequence.Create(CSharp.RankSpecifier.New(1)))),
                    CSharp.Identifier.New(n.ExtraPositional.Name.Name));
            }
            if (fixedParameters != null && paramArray != null)
                return CSharp.FormalParameterList.NewFixedAndParams(fixedParameters, paramArray);
            else if (fixedParameters != null)
                return CSharp.FormalParameterList.NewFixedOnly(fixedParameters);
            else
                return CSharp.FormalParameterList.NewParamsOnly(paramArray);
        }

        public virtual CSharp.InterfaceMemberDeclaration TranslateInterfaceMemberDeclarator(InterfaceMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return n.AcceptInterfaceMemberDeclaratorTranslator(this);
        }

        public virtual CSharp.InterfaceMemberDeclaration TranslateMethodInterfaceMemberDeclarator(MethodInterfaceMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.ReturnType returnType;
            if (n.ResultType != null)
                returnType = CSharp.ReturnType.NewValued(TranslateTypeExpression(n.ResultType));
            else
                returnType = CSharp.ReturnType.NewVoid();
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.FormalParameterList parameters = TranslateAsFormalParameterList(n.Parameters);
            CSharp.InterfaceMethodDeclaration declaration = CSharp.InterfaceMethodDeclaration.New(null, false, returnType, name, null, parameters);
            return CSharp.InterfaceMemberDeclaration.NewMethod(declaration);
        }

        public virtual CSharp.InterfaceMemberDeclaration TranslatePropertyInterfaceMemberDeclarator(PropertyInterfaceMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.InterfaceAccessors accessors;
            if (n.IsMutable)
            {
                CSharp.InterfaceGetAccessor getter = CSharp.InterfaceGetAccessor.New();
                CSharp.InterfaceSetAccessor setter = CSharp.InterfaceSetAccessor.New();
                accessors = CSharp.InterfaceAccessors.NewGetSet(getter, setter);
            }
            else
            {
                CSharp.InterfaceGetAccessor getter = CSharp.InterfaceGetAccessor.New();
                accessors = CSharp.InterfaceAccessors.NewGetOnly(getter);
            }
            CSharp.InterfacePropertyDeclaration declaration = CSharp.InterfacePropertyDeclaration.New(null, false, type, name, accessors);
            return CSharp.InterfaceMemberDeclaration.NewProperty(declaration);
        }

        public virtual CSharp.InterfaceMemberDeclaration TranslateEventInterfaceMemberDeclarator(EventInterfaceMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.InterfaceEventDeclaration declaration = CSharp.InterfaceEventDeclaration.New(null, false, type, name);
            return CSharp.InterfaceMemberDeclaration.NewEvent(declaration);
        }

        public virtual CSharp.InterfaceMemberDeclaration TranslateIndexerInterfaceMemberDeclarator(IndexerInterfaceMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.FormalParameterList parameters = TranslateAsFormalParameterList(n.Parameters);
            CSharp.InterfaceAccessors accessors;
            if (n.IsMutable)
            {
                CSharp.InterfaceGetAccessor getter = CSharp.InterfaceGetAccessor.New();
                CSharp.InterfaceSetAccessor setter = CSharp.InterfaceSetAccessor.New();
                accessors = CSharp.InterfaceAccessors.NewGetSet(getter, setter);
            }
            else
            {
                CSharp.InterfaceGetAccessor getter = CSharp.InterfaceGetAccessor.New();
                accessors = CSharp.InterfaceAccessors.NewGetOnly(getter);
            }
            CSharp.InterfaceIndexerDeclaration declaration = CSharp.InterfaceIndexerDeclaration.New(null, false, type, parameters, accessors);
            return CSharp.InterfaceMemberDeclaration.NewIndexer(declaration);
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateClassMemberDeclarator(ClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return n.AcceptClassMemberDeclaratorTranslator(this);
        }

        public virtual CSharp.FieldModifiers TranslateClassMemberAccessibilityAsFieldModifiers(ClassMemberAccessibility n)
        {
            switch (n)
            {
                case ClassMemberAccessibility.Public:
                    return CSharp.FieldModifiers.New(Sequence.Create(CSharp.FieldModifier.NewPublic()));
                case ClassMemberAccessibility.Protected:
                    return CSharp.FieldModifiers.New(Sequence.Create(CSharp.FieldModifier.NewProtected()));
                case ClassMemberAccessibility.Private:
                    return CSharp.FieldModifiers.New(Sequence.Create(CSharp.FieldModifier.NewPrivate()));
                case ClassMemberAccessibility.Internal:
                    return CSharp.FieldModifiers.New(Sequence.Create(CSharp.FieldModifier.NewInternal()));
                case ClassMemberAccessibility.InternalProtected:
                    return CSharp.FieldModifiers.New(Sequence.Create(CSharp.FieldModifier.NewInternal(), CSharp.FieldModifier.NewProtected()));
                case ClassMemberAccessibility.PrivateProtected:
                    return CSharp.FieldModifiers.New(Sequence.Create(CSharp.FieldModifier.NewPrivate(), CSharp.FieldModifier.NewProtected()));
                case ClassMemberAccessibility.NewPublic:
                    return CSharp.FieldModifiers.New(Sequence.Create(CSharp.FieldModifier.NewNew(), CSharp.FieldModifier.NewPublic()));
                case ClassMemberAccessibility.NewProtected:
                    return CSharp.FieldModifiers.New(Sequence.Create(CSharp.FieldModifier.NewNew(), CSharp.FieldModifier.NewProtected()));
                case ClassMemberAccessibility.NewPrivate:
                    return CSharp.FieldModifiers.New(Sequence.Create(CSharp.FieldModifier.NewNew(), CSharp.FieldModifier.NewPrivate()));
                case ClassMemberAccessibility.NewInternal:
                    return CSharp.FieldModifiers.New(Sequence.Create(CSharp.FieldModifier.NewNew(), CSharp.FieldModifier.NewInternal()));
                case ClassMemberAccessibility.NewInternalProtected:
                    return CSharp.FieldModifiers.New(Sequence.Create(CSharp.FieldModifier.NewNew(), CSharp.FieldModifier.NewInternal(), CSharp.FieldModifier.NewProtected()));
                case ClassMemberAccessibility.NewPrivateProtected:
                    return CSharp.FieldModifiers.New(Sequence.Create(CSharp.FieldModifier.NewNew(), CSharp.FieldModifier.NewPrivate(), CSharp.FieldModifier.NewProtected()));
                case ClassMemberAccessibility.New:
                    return CSharp.FieldModifiers.New(Sequence.Create(CSharp.FieldModifier.NewNew()));
                default:
                    throw new ArgumentException(SR.InvalidClassMemberAccessibility, nameof(n));
            }
        }

        public virtual CSharp.EventModifiers TranslateClassMemberAccessibilityAsEventModifiers(ClassMemberAccessibility n)
        {
            switch (n)
            {
                case ClassMemberAccessibility.Public:
                    return CSharp.EventModifiers.New(Sequence.Create(CSharp.EventModifier.NewPublic()));
                case ClassMemberAccessibility.Protected:
                    return CSharp.EventModifiers.New(Sequence.Create(CSharp.EventModifier.NewProtected()));
                case ClassMemberAccessibility.Private:
                    return CSharp.EventModifiers.New(Sequence.Create(CSharp.EventModifier.NewPrivate()));
                case ClassMemberAccessibility.Internal:
                    return CSharp.EventModifiers.New(Sequence.Create(CSharp.EventModifier.NewInternal()));
                case ClassMemberAccessibility.InternalProtected:
                    return CSharp.EventModifiers.New(Sequence.Create(CSharp.EventModifier.NewInternal(), CSharp.EventModifier.NewProtected()));
                case ClassMemberAccessibility.PrivateProtected:
                    return CSharp.EventModifiers.New(Sequence.Create(CSharp.EventModifier.NewPrivate(), CSharp.EventModifier.NewProtected()));
                case ClassMemberAccessibility.NewPublic:
                    return CSharp.EventModifiers.New(Sequence.Create(CSharp.EventModifier.NewNew(), CSharp.EventModifier.NewPublic()));
                case ClassMemberAccessibility.NewProtected:
                    return CSharp.EventModifiers.New(Sequence.Create(CSharp.EventModifier.NewNew(), CSharp.EventModifier.NewProtected()));
                case ClassMemberAccessibility.NewPrivate:
                    return CSharp.EventModifiers.New(Sequence.Create(CSharp.EventModifier.NewNew(), CSharp.EventModifier.NewPrivate()));
                case ClassMemberAccessibility.NewInternal:
                    return CSharp.EventModifiers.New(Sequence.Create(CSharp.EventModifier.NewNew(), CSharp.EventModifier.NewInternal()));
                case ClassMemberAccessibility.NewInternalProtected:
                    return CSharp.EventModifiers.New(Sequence.Create(CSharp.EventModifier.NewNew(), CSharp.EventModifier.NewInternal(), CSharp.EventModifier.NewProtected()));
                case ClassMemberAccessibility.NewPrivateProtected:
                    return CSharp.EventModifiers.New(Sequence.Create(CSharp.EventModifier.NewNew(), CSharp.EventModifier.NewPrivate(), CSharp.EventModifier.NewProtected()));
                case ClassMemberAccessibility.New:
                    return CSharp.EventModifiers.New(Sequence.Create(CSharp.EventModifier.NewNew()));
                default:
                    throw new ArgumentException(SR.InvalidClassMemberAccessibility, nameof(n));
            }
        }

        public virtual CSharp.PropertyModifiers TranslateClassMemberAccessibilityAsPropertyModifiers(ClassMemberAccessibility n)
        {
            switch (n)
            {
                case ClassMemberAccessibility.Public:
                    return CSharp.PropertyModifiers.New(Sequence.Create(CSharp.PropertyModifier.NewPublic()));
                case ClassMemberAccessibility.Protected:
                    return CSharp.PropertyModifiers.New(Sequence.Create(CSharp.PropertyModifier.NewProtected()));
                case ClassMemberAccessibility.Private:
                    return CSharp.PropertyModifiers.New(Sequence.Create(CSharp.PropertyModifier.NewPrivate()));
                case ClassMemberAccessibility.Internal:
                    return CSharp.PropertyModifiers.New(Sequence.Create(CSharp.PropertyModifier.NewInternal()));
                case ClassMemberAccessibility.InternalProtected:
                    return CSharp.PropertyModifiers.New(Sequence.Create(CSharp.PropertyModifier.NewInternal(), CSharp.PropertyModifier.NewProtected()));
                case ClassMemberAccessibility.PrivateProtected:
                    return CSharp.PropertyModifiers.New(Sequence.Create(CSharp.PropertyModifier.NewPrivate(), CSharp.PropertyModifier.NewProtected()));
                case ClassMemberAccessibility.NewPublic:
                    return CSharp.PropertyModifiers.New(Sequence.Create(CSharp.PropertyModifier.NewNew(), CSharp.PropertyModifier.NewPublic()));
                case ClassMemberAccessibility.NewProtected:
                    return CSharp.PropertyModifiers.New(Sequence.Create(CSharp.PropertyModifier.NewNew(), CSharp.PropertyModifier.NewProtected()));
                case ClassMemberAccessibility.NewPrivate:
                    return CSharp.PropertyModifiers.New(Sequence.Create(CSharp.PropertyModifier.NewNew(), CSharp.PropertyModifier.NewPrivate()));
                case ClassMemberAccessibility.NewInternal:
                    return CSharp.PropertyModifiers.New(Sequence.Create(CSharp.PropertyModifier.NewNew(), CSharp.PropertyModifier.NewInternal()));
                case ClassMemberAccessibility.NewInternalProtected:
                    return CSharp.PropertyModifiers.New(Sequence.Create(CSharp.PropertyModifier.NewNew(), CSharp.PropertyModifier.NewInternal(), CSharp.PropertyModifier.NewProtected()));
                case ClassMemberAccessibility.NewPrivateProtected:
                    return CSharp.PropertyModifiers.New(Sequence.Create(CSharp.PropertyModifier.NewNew(), CSharp.PropertyModifier.NewPrivate(), CSharp.PropertyModifier.NewProtected()));
                case ClassMemberAccessibility.New:
                    return CSharp.PropertyModifiers.New(Sequence.Create(CSharp.PropertyModifier.NewNew()));
                default:
                    throw new ArgumentException(SR.InvalidClassMemberAccessibility, nameof(n));
            }
        }

        public virtual CSharp.IndexerModifiers TranslateClassMemberAccessibilityAsIndexerModifiers(ClassMemberAccessibility n)
        {
            switch (n)
            {
                case ClassMemberAccessibility.Public:
                    return CSharp.IndexerModifiers.New(Sequence.Create(CSharp.IndexerModifier.NewPublic()));
                case ClassMemberAccessibility.Protected:
                    return CSharp.IndexerModifiers.New(Sequence.Create(CSharp.IndexerModifier.NewProtected()));
                case ClassMemberAccessibility.Private:
                    return CSharp.IndexerModifiers.New(Sequence.Create(CSharp.IndexerModifier.NewPrivate()));
                case ClassMemberAccessibility.Internal:
                    return CSharp.IndexerModifiers.New(Sequence.Create(CSharp.IndexerModifier.NewInternal()));
                case ClassMemberAccessibility.InternalProtected:
                    return CSharp.IndexerModifiers.New(Sequence.Create(CSharp.IndexerModifier.NewInternal(), CSharp.IndexerModifier.NewProtected()));
                case ClassMemberAccessibility.PrivateProtected:
                    return CSharp.IndexerModifiers.New(Sequence.Create(CSharp.IndexerModifier.NewPrivate(), CSharp.IndexerModifier.NewProtected()));
                case ClassMemberAccessibility.NewPublic:
                    return CSharp.IndexerModifiers.New(Sequence.Create(CSharp.IndexerModifier.NewNew(), CSharp.IndexerModifier.NewPublic()));
                case ClassMemberAccessibility.NewProtected:
                    return CSharp.IndexerModifiers.New(Sequence.Create(CSharp.IndexerModifier.NewNew(), CSharp.IndexerModifier.NewProtected()));
                case ClassMemberAccessibility.NewPrivate:
                    return CSharp.IndexerModifiers.New(Sequence.Create(CSharp.IndexerModifier.NewNew(), CSharp.IndexerModifier.NewPrivate()));
                case ClassMemberAccessibility.NewInternal:
                    return CSharp.IndexerModifiers.New(Sequence.Create(CSharp.IndexerModifier.NewNew(), CSharp.IndexerModifier.NewInternal()));
                case ClassMemberAccessibility.NewInternalProtected:
                    return CSharp.IndexerModifiers.New(Sequence.Create(CSharp.IndexerModifier.NewNew(), CSharp.IndexerModifier.NewInternal(), CSharp.IndexerModifier.NewProtected()));
                case ClassMemberAccessibility.NewPrivateProtected:
                    return CSharp.IndexerModifiers.New(Sequence.Create(CSharp.IndexerModifier.NewNew(), CSharp.IndexerModifier.NewPrivate(), CSharp.IndexerModifier.NewProtected()));
                case ClassMemberAccessibility.New:
                    return CSharp.IndexerModifiers.New(Sequence.Create(CSharp.IndexerModifier.NewNew()));
                default:
                    throw new ArgumentException(SR.InvalidClassMemberAccessibility, nameof(n));
            }
        }

        public virtual CSharp.MethodModifiers TranslateClassMemberAccessibilityAsMethodModifiers(ClassMemberAccessibility n)
        {
            switch (n)
            {
                case ClassMemberAccessibility.Public:
                    return CSharp.MethodModifiers.New(Sequence.Create(CSharp.MethodModifier.NewPublic()));
                case ClassMemberAccessibility.Protected:
                    return CSharp.MethodModifiers.New(Sequence.Create(CSharp.MethodModifier.NewProtected()));
                case ClassMemberAccessibility.Private:
                    return CSharp.MethodModifiers.New(Sequence.Create(CSharp.MethodModifier.NewPrivate()));
                case ClassMemberAccessibility.Internal:
                    return CSharp.MethodModifiers.New(Sequence.Create(CSharp.MethodModifier.NewInternal()));
                case ClassMemberAccessibility.InternalProtected:
                    return CSharp.MethodModifiers.New(Sequence.Create(CSharp.MethodModifier.NewInternal(), CSharp.MethodModifier.NewProtected()));
                case ClassMemberAccessibility.PrivateProtected:
                    return CSharp.MethodModifiers.New(Sequence.Create(CSharp.MethodModifier.NewPrivate(), CSharp.MethodModifier.NewProtected()));
                case ClassMemberAccessibility.NewPublic:
                    return CSharp.MethodModifiers.New(Sequence.Create(CSharp.MethodModifier.NewNew(), CSharp.MethodModifier.NewPublic()));
                case ClassMemberAccessibility.NewProtected:
                    return CSharp.MethodModifiers.New(Sequence.Create(CSharp.MethodModifier.NewNew(), CSharp.MethodModifier.NewProtected()));
                case ClassMemberAccessibility.NewPrivate:
                    return CSharp.MethodModifiers.New(Sequence.Create(CSharp.MethodModifier.NewNew(), CSharp.MethodModifier.NewPrivate()));
                case ClassMemberAccessibility.NewInternal:
                    return CSharp.MethodModifiers.New(Sequence.Create(CSharp.MethodModifier.NewNew(), CSharp.MethodModifier.NewInternal()));
                case ClassMemberAccessibility.NewInternalProtected:
                    return CSharp.MethodModifiers.New(Sequence.Create(CSharp.MethodModifier.NewNew(), CSharp.MethodModifier.NewInternal(), CSharp.MethodModifier.NewProtected()));
                case ClassMemberAccessibility.NewPrivateProtected:
                    return CSharp.MethodModifiers.New(Sequence.Create(CSharp.MethodModifier.NewNew(), CSharp.MethodModifier.NewPrivate(), CSharp.MethodModifier.NewProtected()));
                case ClassMemberAccessibility.New:
                    return CSharp.MethodModifiers.New(Sequence.Create(CSharp.MethodModifier.NewNew()));
                default:
                    throw new ArgumentException(SR.InvalidClassMemberAccessibility, nameof(n));
            }
        }

        public virtual CSharp.ConstructorModifiers TranslateClassMemberAccessibilityAsConstructorModifiers(ClassMemberAccessibility n)
        {
            switch (n)
            {
                case ClassMemberAccessibility.Public:
                    return CSharp.ConstructorModifiers.New(Sequence.Create(CSharp.ConstructorModifier.NewPublic()));
                case ClassMemberAccessibility.Protected:
                    return CSharp.ConstructorModifiers.New(Sequence.Create(CSharp.ConstructorModifier.NewProtected()));
                case ClassMemberAccessibility.Private:
                    return CSharp.ConstructorModifiers.New(Sequence.Create(CSharp.ConstructorModifier.NewPrivate()));
                case ClassMemberAccessibility.Internal:
                    return CSharp.ConstructorModifiers.New(Sequence.Create(CSharp.ConstructorModifier.NewInternal()));
                case ClassMemberAccessibility.InternalProtected:
                    return CSharp.ConstructorModifiers.New(Sequence.Create(CSharp.ConstructorModifier.NewInternal(), CSharp.ConstructorModifier.NewProtected()));
                case ClassMemberAccessibility.PrivateProtected:
                    return CSharp.ConstructorModifiers.New(Sequence.Create(CSharp.ConstructorModifier.NewPrivate(), CSharp.ConstructorModifier.NewProtected()));
                default:
                    throw new ArgumentException(SR.InvalidClassMemberAccessibility, nameof(n));
            }
        }

        public virtual CSharp.EventModifiers TranslateClassMemberVirtualModifierAsEventModifiers(ClassMemberVirtualModifier n)
        {
            switch (n)
            {
                case ClassMemberVirtualModifier.Default:
                    return CSharp.EventModifiers.New(Sequence.Create(CSharp.EventModifier.NewVirtual()));
                case ClassMemberVirtualModifier.Override:
                    return CSharp.EventModifiers.New(Sequence.Create(CSharp.EventModifier.NewOverride()));
                case ClassMemberVirtualModifier.Sealed:
                    return CSharp.EventModifiers.New(Sequence.Create(CSharp.EventModifier.NewSealed(), CSharp.EventModifier.NewOverride()));
                default:
                    throw new ArgumentException(SR.InvalidClassMemberVirtualModifier, nameof(n));
            }
        }

        public virtual CSharp.PropertyModifiers TranslateClassMemberVirtualModifierAsPropertyModifiers(ClassMemberVirtualModifier n)
        {
            switch (n)
            {
                case ClassMemberVirtualModifier.Default:
                    return CSharp.PropertyModifiers.New(Sequence.Create(CSharp.PropertyModifier.NewVirtual()));
                case ClassMemberVirtualModifier.Override:
                    return CSharp.PropertyModifiers.New(Sequence.Create(CSharp.PropertyModifier.NewOverride()));
                case ClassMemberVirtualModifier.Sealed:
                    return CSharp.PropertyModifiers.New(Sequence.Create(CSharp.PropertyModifier.NewSealed(), CSharp.PropertyModifier.NewOverride()));
                default:
                    throw new ArgumentException(SR.InvalidClassMemberVirtualModifier, nameof(n));
            }
        }

        public virtual CSharp.IndexerModifiers TranslateClassMemberVirtualModifierAsIndexerModifiers(ClassMemberVirtualModifier n)
        {
            switch (n)
            {
                case ClassMemberVirtualModifier.Default:
                    return CSharp.IndexerModifiers.New(Sequence.Create(CSharp.IndexerModifier.NewVirtual()));
                case ClassMemberVirtualModifier.Override:
                    return CSharp.IndexerModifiers.New(Sequence.Create(CSharp.IndexerModifier.NewOverride()));
                case ClassMemberVirtualModifier.Sealed:
                    return CSharp.IndexerModifiers.New(Sequence.Create(CSharp.IndexerModifier.NewSealed(), CSharp.IndexerModifier.NewOverride()));
                default:
                    throw new ArgumentException(SR.InvalidClassMemberVirtualModifier, nameof(n));
            }
        }

        public virtual CSharp.MethodModifiers TranslateClassMemberVirtualModifierAsMethodModifiers(ClassMemberVirtualModifier n)
        {
            switch (n)
            {
                case ClassMemberVirtualModifier.Default:
                    return CSharp.MethodModifiers.New(Sequence.Create(CSharp.MethodModifier.NewVirtual()));
                case ClassMemberVirtualModifier.Override:
                    return CSharp.MethodModifiers.New(Sequence.Create(CSharp.MethodModifier.NewOverride()));
                case ClassMemberVirtualModifier.Sealed:
                    return CSharp.MethodModifiers.New(Sequence.Create(CSharp.MethodModifier.NewSealed(), CSharp.MethodModifier.NewOverride()));
                default:
                    throw new ArgumentException(SR.InvalidClassMemberVirtualModifier, nameof(n));
            }
        }

        public virtual CSharp.Block TranslateClassMethodBodyAsEventBlock(ClassMethodBody n)
        {
            if (n == null)
                return CSharp.Block.New();
            if (n.IsExpr)
            {
                CSharp.Statement statement = CSharp.Statement.NewExpression(CSharp.StatementExpression.New(TranslateExpression(n.AsExpr.Value)));
                return CSharp.Block.New(CSharp.StatementList.New(Sequence.Create(statement)));
            }
            else
            {
                CSharp.Statement statement = TranslateStatement(n.AsBlock.Actions);
                return ExtractOrWrapAsBlock(statement);
            }
        }

        public virtual CSharp.Block TranslateClassMethodBodyAsPropertyBlock(ClassMethodBody n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.IsExpr)
            {
                CSharp.Expression value = TranslateExpression(n.AsExpr.Value);
                CSharp.Statement statement = CSharp.Statement.NewReturn(value);
                return CSharp.Block.New(CSharp.StatementList.New(Sequence.Create(statement)));
            }
            else
            {
                CSharp.Statement statement = TranslateStatement(n.AsBlock.Actions);
                return ExtractOrWrapAsBlock(statement);
            }
        }

        public virtual CSharp.Block TranslateClassMethodBodyAsIndexerBlock(ClassMethodBody n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.IsExpr)
            {
                CSharp.Expression value = TranslateExpression(n.AsExpr.Value);
                CSharp.Statement statement = CSharp.Statement.NewReturn(value);
                return CSharp.Block.New(CSharp.StatementList.New(Sequence.Create(statement)));
            }
            else
            {
                CSharp.Statement statement = TranslateStatement(n.AsBlock.Actions);
                return ExtractOrWrapAsBlock(statement);
            }
        }

        public virtual CSharp.Block TranslateClassMethodBodyAsMethodBlock(ClassMethodBody n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.IsExpr)
            {
                CSharp.Expression value = TranslateExpression(n.AsExpr.Value);
                CSharp.Statement statement = CSharp.Statement.NewReturn(value);
                return CSharp.Block.New(CSharp.StatementList.New(Sequence.Create(statement)));
            }
            else
            {
                CSharp.Statement statement = TranslateStatement(n.AsBlock.Actions);
                return ExtractOrWrapAsBlock(statement);
            }
        }

        public virtual CSharp.Block TranslateClassMethodBodyAsConstructorBlock(ClassMethodBody n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (n.IsExpr)
            {
                CSharp.Statement statement = CSharp.Statement.NewExpression(CSharp.StatementExpression.New(TranslateExpression(n.AsExpr.Value)));
                return CSharp.Block.New(CSharp.StatementList.New(Sequence.Create(statement)));
            }
            else
            {
                CSharp.Statement statement = TranslateStatement(n.AsBlock.Actions);
                return ExtractOrWrapAsBlock(statement);
            }
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateFieldClassMemberDeclarator(FieldClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.FieldModifiers modifiers = TranslateClassMemberAccessibilityAsFieldModifiers(n.Access);
            if (n.IsStatic)
                modifiers = modifiers.WithItems(Sequence.Append(modifiers.Items, CSharp.FieldModifier.NewStatic()));
            if (!n.IsMutable)
                modifiers = modifiers.WithItems(Sequence.Append(modifiers.Items, CSharp.FieldModifier.NewReadonly()));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.Expression value = n.Value != null ? TranslateExpression(n.Value) : null;
            CSharp.VariableDeclarator declarator = CSharp.VariableDeclarator.New(name, value != null ? CSharp.VariableInitializer.NewSingle(value) : null);
            CSharp.VariableDeclarators declarators = CSharp.VariableDeclarators.New(Sequence.Create(declarator));
            CSharp.FieldDeclaration declaration = CSharp.FieldDeclaration.New(null, modifiers, type, declarators);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewField(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateEventClassMemberDeclarator(EventClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.EventModifiers modifiers = TranslateClassMemberAccessibilityAsEventModifiers(n.Access);
            if (n.IsStatic)
                modifiers = modifiers.WithItems(Sequence.Append(modifiers.Items, CSharp.EventModifier.NewStatic()));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.VariableDeclarator declarator = CSharp.VariableDeclarator.New(name);
            CSharp.VariableDeclarators declarators = CSharp.VariableDeclarators.New(Sequence.Create(declarator));
            CSharp.EventDeclaration declaration = CSharp.EventDeclaration.NewAuto(null, modifiers, type, declarators);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewEvent(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateEventBlockClassMemberDeclarator(EventBlockClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.EventModifiers modifiers = TranslateClassMemberAccessibilityAsEventModifiers(n.Access);
            if (n.IsStatic)
                modifiers = modifiers.WithItems(Sequence.Append(modifiers.Items, CSharp.EventModifier.NewStatic()));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.MemberName memberName = CSharp.MemberName.NewSimple(name);
            CSharp.AddAccessorDeclaration add = CSharp.AddAccessorDeclaration.New(null, TranslateClassMethodBodyAsEventBlock(n.Adder));
            CSharp.RemoveAccessorDeclaration remove = CSharp.RemoveAccessorDeclaration.New(null, TranslateClassMethodBodyAsEventBlock(n.Remover));
            CSharp.EventAccessorDeclarations accessors = CSharp.EventAccessorDeclarations.NewAddRemove(add, remove);
            CSharp.EventDeclaration declaration = CSharp.EventDeclaration.NewExplicit(null, modifiers, type, memberName, accessors);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewEvent(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateVirtualEventClassMemberDeclarator(VirtualEventClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.EventModifiers modifiers = TranslateClassMemberAccessibilityAsEventModifiers(n.Access);
            modifiers = modifiers.WithItems(Sequence.Concat(modifiers.Items, TranslateClassMemberVirtualModifierAsEventModifiers(n.Modifier).Items));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.VariableDeclarator declarator = CSharp.VariableDeclarator.New(name);
            CSharp.VariableDeclarators declarators = CSharp.VariableDeclarators.New(Sequence.Create(declarator));
            CSharp.EventDeclaration declaration = CSharp.EventDeclaration.NewAuto(null, modifiers, type, declarators);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewEvent(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateVirtualEventBlockClassMemberDeclarator(VirtualEventBlockClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.EventModifiers modifiers = TranslateClassMemberAccessibilityAsEventModifiers(n.Access);
            modifiers = modifiers.WithItems(Sequence.Concat(modifiers.Items, TranslateClassMemberVirtualModifierAsEventModifiers(n.Modifier).Items));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.MemberName memberName = CSharp.MemberName.NewSimple(name);
            CSharp.AddAccessorDeclaration add = CSharp.AddAccessorDeclaration.New(null, TranslateClassMethodBodyAsEventBlock(n.Adder));
            CSharp.RemoveAccessorDeclaration remove = CSharp.RemoveAccessorDeclaration.New(null, TranslateClassMethodBodyAsEventBlock(n.Remover));
            CSharp.EventAccessorDeclarations accessors = CSharp.EventAccessorDeclarations.NewAddRemove(add, remove);
            CSharp.EventDeclaration declaration = CSharp.EventDeclaration.NewExplicit(null, modifiers, type, memberName, accessors);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewEvent(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateAbstractEventClassMemberDeclarator(AbstractEventClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.EventModifiers modifiers = TranslateClassMemberAccessibilityAsEventModifiers(n.Access);
            modifiers = modifiers.WithItems(Sequence.Append(modifiers.Items, CSharp.EventModifier.NewAbstract()));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.VariableDeclarator declarator = CSharp.VariableDeclarator.New(name);
            CSharp.VariableDeclarators declarators = CSharp.VariableDeclarators.New(Sequence.Create(declarator));
            CSharp.EventDeclaration declaration = CSharp.EventDeclaration.NewAuto(null, modifiers, type, declarators);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewEvent(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateExplicitEventImplClassMemberDeclarator(ExplicitEventImplClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            EventClassMemberDeclarator privateDecl = EventClassMemberDeclarator.New(ClassMemberAccessibility.Private, false, n.Name, n.Type);
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.InterfaceType targetType = CSharp.InterfaceType.New(CSharp.TypeName.New(TranslateTypeName(n.Target)));
            CSharp.MemberName memberName = CSharp.MemberName.NewExplicit(targetType, name);
            CSharp.UnaryExpression eventRef = CSharp.UnaryExpression.NewSimpleName(CSharp.SimpleName.New(name));
            CSharp.Expression valueRef = CSharp.Expression.NewSimpleName(CSharp.SimpleName.New(CSharp.Identifier.New("value")));
            CSharp.AddAccessorDeclaration add = CSharp.AddAccessorDeclaration.New(null, CSharp.Block.New(CSharp.StatementList.New(
                Sequence.Create(CSharp.Statement.NewExpression(CSharp.StatementExpression.New(
                    CSharp.Expression.NewAssignment(eventRef, CSharp.AssignmentOperator.NewAddAssign(), valueRef)))))));
            CSharp.RemoveAccessorDeclaration remove = CSharp.RemoveAccessorDeclaration.New(null, CSharp.Block.New(CSharp.StatementList.New(
                Sequence.Create(CSharp.Statement.NewExpression(CSharp.StatementExpression.New(
                    CSharp.Expression.NewAssignment(eventRef, CSharp.AssignmentOperator.NewSubtractAssign(), valueRef)))))));
            CSharp.EventAccessorDeclarations accessors = CSharp.EventAccessorDeclarations.NewAddRemove(add, remove);
            CSharp.EventDeclaration declaration = CSharp.EventDeclaration.NewExplicit(null, null, type, memberName, accessors);
            return Sequence.Append(TranslateClassMemberDeclarator(privateDecl), CSharp.ClassMemberDeclaration.NewEvent(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateExplicitEventImplBlockClassMemberDeclarator(ExplicitEventImplBlockClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.InterfaceType targetType = CSharp.InterfaceType.New(CSharp.TypeName.New(TranslateTypeName(n.Target)));
            CSharp.MemberName memberName = CSharp.MemberName.NewExplicit(targetType, name);
            CSharp.AddAccessorDeclaration add = CSharp.AddAccessorDeclaration.New(null, TranslateClassMethodBodyAsEventBlock(n.Adder));
            CSharp.RemoveAccessorDeclaration remove = CSharp.RemoveAccessorDeclaration.New(null, TranslateClassMethodBodyAsEventBlock(n.Remover));
            CSharp.EventAccessorDeclarations accessors = CSharp.EventAccessorDeclarations.NewAddRemove(add, remove);
            CSharp.EventDeclaration declaration = CSharp.EventDeclaration.NewExplicit(null, null, type, memberName, accessors);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewEvent(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslatePropertyClassMemberDeclarator(PropertyClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.PropertyModifiers modifiers = TranslateClassMemberAccessibilityAsPropertyModifiers(n.Access);
            if (n.IsStatic)
                modifiers = modifiers.WithItems(Sequence.Append(modifiers.Items, CSharp.PropertyModifier.NewStatic()));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.MemberName memberName = CSharp.MemberName.NewSimple(name);
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.PropertyBody body = CSharp.PropertyBody.NewFast(value);
            CSharp.PropertyDeclaration declaration = CSharp.PropertyDeclaration.New(null, modifiers, type, memberName, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewProperty(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslatePropertyFieldClassMemberDeclarator(PropertyFieldClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.PropertyModifiers modifiers = TranslateClassMemberAccessibilityAsPropertyModifiers(n.Access);
            if (n.IsStatic)
                modifiers = modifiers.WithItems(Sequence.Append(modifiers.Items, CSharp.PropertyModifier.NewStatic()));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.MemberName memberName = CSharp.MemberName.NewSimple(name);
            CSharp.AccessorDeclarations accessors;
            if (n.IsMutable)
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewPartial());
                CSharp.SetAccessorDeclaration setter = CSharp.SetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewPartial());
                accessors = CSharp.AccessorDeclarations.NewGetSet(getter, setter);
            }
            else
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewPartial());
                accessors = CSharp.AccessorDeclarations.NewGetOnly(getter);
            }
            CSharp.PropertyBody body;
            if (n.Value == null)
                body = CSharp.PropertyBody.NewFull(accessors);
            else
            {
                CSharp.Expression value = TranslateExpression(n.Value);
                CSharp.VariableInitializer init = CSharp.VariableInitializer.NewSingle(value);
                CSharp.PropertyInitializer initializer = CSharp.PropertyInitializer.New(init);
                body = CSharp.PropertyBody.NewFull(accessors, initializer);
            }
            CSharp.PropertyDeclaration declaration = CSharp.PropertyDeclaration.New(null, modifiers, type, memberName, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewProperty(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslatePropertyBlockClassMemberDeclarator(PropertyBlockClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.PropertyModifiers modifiers = TranslateClassMemberAccessibilityAsPropertyModifiers(n.Access);
            if (n.IsStatic)
                modifiers = modifiers.WithItems(Sequence.Append(modifiers.Items, CSharp.PropertyModifier.NewStatic()));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.MemberName memberName = CSharp.MemberName.NewSimple(name);
            CSharp.AccessorDeclarations accessors;
            if (n.Setter != null)
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewFull(TranslateClassMethodBodyAsPropertyBlock(n.Getter)));
                CSharp.SetAccessorDeclaration setter = CSharp.SetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewFull(TranslateClassMethodBodyAsPropertyBlock(n.Setter)));
                accessors = CSharp.AccessorDeclarations.NewGetSet(getter, setter);
            }
            else
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewFull(TranslateClassMethodBodyAsPropertyBlock(n.Getter)));
                accessors = CSharp.AccessorDeclarations.NewGetOnly(getter);
            }
            CSharp.PropertyBody body = CSharp.PropertyBody.NewFull(accessors);
            CSharp.PropertyDeclaration declaration = CSharp.PropertyDeclaration.New(null, modifiers, type, memberName, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewProperty(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateVirtualPropertyClassMemberDeclarator(VirtualPropertyClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.PropertyModifiers modifiers = TranslateClassMemberAccessibilityAsPropertyModifiers(n.Access);
            modifiers = modifiers.WithItems(Sequence.Concat(modifiers.Items, TranslateClassMemberVirtualModifierAsPropertyModifiers(n.Modifier).Items));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.MemberName memberName = CSharp.MemberName.NewSimple(name);
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.PropertyBody body = CSharp.PropertyBody.NewFast(value);
            CSharp.PropertyDeclaration declaration = CSharp.PropertyDeclaration.New(null, modifiers, type, memberName, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewProperty(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateVirtualPropertyFieldClassMemberDeclarator(VirtualPropertyFieldClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.PropertyModifiers modifiers = TranslateClassMemberAccessibilityAsPropertyModifiers(n.Access);
            modifiers = modifiers.WithItems(Sequence.Concat(modifiers.Items, TranslateClassMemberVirtualModifierAsPropertyModifiers(n.Modifier).Items));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.MemberName memberName = CSharp.MemberName.NewSimple(name);
            CSharp.AccessorDeclarations accessors;
            if (n.IsMutable)
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewPartial());
                CSharp.SetAccessorDeclaration setter = CSharp.SetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewPartial());
                accessors = CSharp.AccessorDeclarations.NewGetSet(getter, setter);
            }
            else
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewPartial());
                accessors = CSharp.AccessorDeclarations.NewGetOnly(getter);
            }
            CSharp.PropertyBody body;
            if (n.Value == null)
                body = CSharp.PropertyBody.NewFull(accessors);
            else
            {
                CSharp.Expression value = TranslateExpression(n.Value);
                CSharp.VariableInitializer init = CSharp.VariableInitializer.NewSingle(value);
                CSharp.PropertyInitializer initializer = CSharp.PropertyInitializer.New(init);
                body = CSharp.PropertyBody.NewFull(accessors, initializer);
            }
            CSharp.PropertyDeclaration declaration = CSharp.PropertyDeclaration.New(null, modifiers, type, memberName, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewProperty(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateVirtualPropertyBlockClassMemberDeclarator(VirtualPropertyBlockClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.PropertyModifiers modifiers = TranslateClassMemberAccessibilityAsPropertyModifiers(n.Access);
            modifiers = modifiers.WithItems(Sequence.Concat(modifiers.Items, TranslateClassMemberVirtualModifierAsPropertyModifiers(n.Modifier).Items));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.MemberName memberName = CSharp.MemberName.NewSimple(name);
            CSharp.AccessorDeclarations accessors;
            if (n.Setter != null)
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewFull(TranslateClassMethodBodyAsPropertyBlock(n.Getter)));
                CSharp.SetAccessorDeclaration setter = CSharp.SetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewFull(TranslateClassMethodBodyAsPropertyBlock(n.Setter)));
                accessors = CSharp.AccessorDeclarations.NewGetSet(getter, setter);
            }
            else
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewFull(TranslateClassMethodBodyAsPropertyBlock(n.Getter)));
                accessors = CSharp.AccessorDeclarations.NewGetOnly(getter);
            }
            CSharp.PropertyBody body = CSharp.PropertyBody.NewFull(accessors);
            CSharp.PropertyDeclaration declaration = CSharp.PropertyDeclaration.New(null, modifiers, type, memberName, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewProperty(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateAbstractPropertyClassMemberDeclarator(AbstractPropertyClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.PropertyModifiers modifiers = TranslateClassMemberAccessibilityAsPropertyModifiers(n.Access);
            modifiers = modifiers.WithItems(Sequence.Append(modifiers.Items, CSharp.PropertyModifier.NewAbstract()));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.MemberName memberName = CSharp.MemberName.NewSimple(name);
            CSharp.AccessorDeclarations accessors;
            if (n.IsMutable)
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewPartial());
                CSharp.SetAccessorDeclaration setter = CSharp.SetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewPartial());
                accessors = CSharp.AccessorDeclarations.NewGetSet(getter, setter);
            }
            else
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewPartial());
                accessors = CSharp.AccessorDeclarations.NewGetOnly(getter);
            }
            CSharp.PropertyBody body = CSharp.PropertyBody.NewFull(accessors);
            CSharp.PropertyDeclaration declaration = CSharp.PropertyDeclaration.New(null, modifiers, type, memberName, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewProperty(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateExplicitPropertyImplClassMemberDeclarator(ExplicitPropertyImplClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.InterfaceType targetType = CSharp.InterfaceType.New(CSharp.TypeName.New(TranslateTypeName(n.Target)));
            CSharp.MemberName memberName = CSharp.MemberName.NewExplicit(targetType, name);
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.PropertyBody body = CSharp.PropertyBody.NewFast(value);
            CSharp.PropertyDeclaration declaration = CSharp.PropertyDeclaration.New(null, null, type, memberName, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewProperty(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateExplicitPropertyImplFieldClassMemberDeclarator(ExplicitPropertyImplFieldClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.InterfaceType targetType = CSharp.InterfaceType.New(CSharp.TypeName.New(TranslateTypeName(n.Target)));
            CSharp.MemberName memberName = CSharp.MemberName.NewExplicit(targetType, name);
            CSharp.AccessorDeclarations accessors;
            if (n.IsMutable)
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewPartial());
                CSharp.SetAccessorDeclaration setter = CSharp.SetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewPartial());
                accessors = CSharp.AccessorDeclarations.NewGetSet(getter, setter);
            }
            else
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewPartial());
                accessors = CSharp.AccessorDeclarations.NewGetOnly(getter);
            }
            CSharp.PropertyBody body;
            if (n.Value == null)
                body = CSharp.PropertyBody.NewFull(accessors);
            else
            {
                CSharp.Expression value = TranslateExpression(n.Value);
                CSharp.VariableInitializer init = CSharp.VariableInitializer.NewSingle(value);
                CSharp.PropertyInitializer initializer = CSharp.PropertyInitializer.New(init);
                body = CSharp.PropertyBody.NewFull(accessors, initializer);
            }
            CSharp.PropertyDeclaration declaration = CSharp.PropertyDeclaration.New(null, null, type, memberName, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewProperty(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateExplicitPropertyImplBlockClassMemberDeclarator(ExplicitPropertyImplBlockClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.InterfaceType targetType = CSharp.InterfaceType.New(CSharp.TypeName.New(TranslateTypeName(n.Target)));
            CSharp.MemberName memberName = CSharp.MemberName.NewExplicit(targetType, name);
            CSharp.AccessorDeclarations accessors;
            if (n.Setter != null)
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewFull(TranslateClassMethodBodyAsPropertyBlock(n.Getter)));
                CSharp.SetAccessorDeclaration setter = CSharp.SetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewFull(TranslateClassMethodBodyAsPropertyBlock(n.Setter)));
                accessors = CSharp.AccessorDeclarations.NewGetSet(getter, setter);
            }
            else
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewFull(TranslateClassMethodBodyAsPropertyBlock(n.Getter)));
                accessors = CSharp.AccessorDeclarations.NewGetOnly(getter);
            }
            CSharp.PropertyBody body = CSharp.PropertyBody.NewFull(accessors);
            CSharp.PropertyDeclaration declaration = CSharp.PropertyDeclaration.New(null, null, type, memberName, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewProperty(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateIndexerClassMemberDeclarator(IndexerClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.IndexerModifiers modifiers = TranslateClassMemberAccessibilityAsIndexerModifiers(n.Access);
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.FormalParameterList parameters = TranslateAsFormalParameterList(n.Parameters);
            CSharp.IndexerDeclarator declarator = CSharp.IndexerDeclarator.NewSimple(type, parameters);
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.IndexerBody body = CSharp.IndexerBody.NewFast(value);
            CSharp.IndexerDeclaration declaration = CSharp.IndexerDeclaration.New(null, modifiers, declarator, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewIndexer(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateIndexerBlockClassMemberDeclarator(IndexerBlockClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.IndexerModifiers modifiers = TranslateClassMemberAccessibilityAsIndexerModifiers(n.Access);
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.FormalParameterList parameters = TranslateAsFormalParameterList(n.Parameters);
            CSharp.IndexerDeclarator declarator = CSharp.IndexerDeclarator.NewSimple(type, parameters);
            CSharp.AccessorDeclarations accessors;
            if (n.Setter != null)
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewFull(TranslateClassMethodBodyAsIndexerBlock(n.Getter)));
                CSharp.SetAccessorDeclaration setter = CSharp.SetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewFull(TranslateClassMethodBodyAsIndexerBlock(n.Setter)));
                accessors = CSharp.AccessorDeclarations.NewGetSet(getter, setter);
            }
            else
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewFull(TranslateClassMethodBodyAsIndexerBlock(n.Getter)));
                accessors = CSharp.AccessorDeclarations.NewGetOnly(getter);
            }
            CSharp.IndexerBody body = CSharp.IndexerBody.NewFull(accessors);
            CSharp.IndexerDeclaration declaration = CSharp.IndexerDeclaration.New(null, modifiers, declarator, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewIndexer(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateVirtualIndexerClassMemberDeclarator(VirtualIndexerClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.IndexerModifiers modifiers = TranslateClassMemberAccessibilityAsIndexerModifiers(n.Access);
            modifiers = modifiers.WithItems(Sequence.Concat(modifiers.Items, TranslateClassMemberVirtualModifierAsIndexerModifiers(n.Modifier).Items));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.FormalParameterList parameters = TranslateAsFormalParameterList(n.Parameters);
            CSharp.IndexerDeclarator declarator = CSharp.IndexerDeclarator.NewSimple(type, parameters);
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.IndexerBody body = CSharp.IndexerBody.NewFast(value);
            CSharp.IndexerDeclaration declaration = CSharp.IndexerDeclaration.New(null, modifiers, declarator, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewIndexer(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateVirtualIndexerBlockClassMemberDeclarator(VirtualIndexerBlockClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.IndexerModifiers modifiers = TranslateClassMemberAccessibilityAsIndexerModifiers(n.Access);
            modifiers = modifiers.WithItems(Sequence.Concat(modifiers.Items, TranslateClassMemberVirtualModifierAsIndexerModifiers(n.Modifier).Items));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.FormalParameterList parameters = TranslateAsFormalParameterList(n.Parameters);
            CSharp.IndexerDeclarator declarator = CSharp.IndexerDeclarator.NewSimple(type, parameters);
            CSharp.AccessorDeclarations accessors;
            if (n.Setter != null)
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewFull(TranslateClassMethodBodyAsIndexerBlock(n.Getter)));
                CSharp.SetAccessorDeclaration setter = CSharp.SetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewFull(TranslateClassMethodBodyAsIndexerBlock(n.Setter)));
                accessors = CSharp.AccessorDeclarations.NewGetSet(getter, setter);
            }
            else
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewFull(TranslateClassMethodBodyAsIndexerBlock(n.Getter)));
                accessors = CSharp.AccessorDeclarations.NewGetOnly(getter);
            }
            CSharp.IndexerBody body = CSharp.IndexerBody.NewFull(accessors);
            CSharp.IndexerDeclaration declaration = CSharp.IndexerDeclaration.New(null, modifiers, declarator, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewIndexer(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateAbstractIndexerClassMemberDeclarator(AbstractIndexerClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.IndexerModifiers modifiers = TranslateClassMemberAccessibilityAsIndexerModifiers(n.Access);
            modifiers = modifiers.WithItems(Sequence.Append(modifiers.Items, CSharp.IndexerModifier.NewAbstract()));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.FormalParameterList parameters = TranslateAsFormalParameterList(n.Parameters);
            CSharp.IndexerDeclarator declarator = CSharp.IndexerDeclarator.NewSimple(type, parameters);
            CSharp.AccessorDeclarations accessors;
            if (n.IsMutable)
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewPartial());
                CSharp.SetAccessorDeclaration setter = CSharp.SetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewPartial());
                accessors = CSharp.AccessorDeclarations.NewGetSet(getter, setter);
            }
            else
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewPartial());
                accessors = CSharp.AccessorDeclarations.NewGetOnly(getter);
            }
            CSharp.IndexerBody body = CSharp.IndexerBody.NewFull(accessors);
            CSharp.IndexerDeclaration declaration = CSharp.IndexerDeclaration.New(null, modifiers, declarator, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewIndexer(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateExplicitIndexerImplClassMemberDeclarator(ExplicitIndexerImplClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.FormalParameterList parameters = TranslateAsFormalParameterList(n.Parameters);
            CSharp.InterfaceType targetType = CSharp.InterfaceType.New(CSharp.TypeName.New(TranslateTypeName(n.Target)));
            CSharp.IndexerDeclarator declarator = CSharp.IndexerDeclarator.NewExplicit(type, targetType, parameters);
            CSharp.Expression value = TranslateExpression(n.Value);
            CSharp.IndexerBody body = CSharp.IndexerBody.NewFast(value);
            CSharp.IndexerDeclaration declaration = CSharp.IndexerDeclaration.New(null, null, declarator, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewIndexer(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateExplicitIndexerImplBlockClassMemberDeclarator(ExplicitIndexerImplBlockClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.Type type = TranslateTypeExpression(n.Type);
            CSharp.FormalParameterList parameters = TranslateAsFormalParameterList(n.Parameters);
            CSharp.InterfaceType targetType = CSharp.InterfaceType.New(CSharp.TypeName.New(TranslateTypeName(n.Target)));
            CSharp.IndexerDeclarator declarator = CSharp.IndexerDeclarator.NewExplicit(type, targetType, parameters);
            CSharp.AccessorDeclarations accessors;
            if (n.Setter != null)
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewFull(TranslateClassMethodBodyAsIndexerBlock(n.Getter)));
                CSharp.SetAccessorDeclaration setter = CSharp.SetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewFull(TranslateClassMethodBodyAsIndexerBlock(n.Setter)));
                accessors = CSharp.AccessorDeclarations.NewGetSet(getter, setter);
            }
            else
            {
                CSharp.GetAccessorDeclaration getter = CSharp.GetAccessorDeclaration.New(null, null, CSharp.AccessorBody.NewFull(TranslateClassMethodBodyAsIndexerBlock(n.Getter)));
                accessors = CSharp.AccessorDeclarations.NewGetOnly(getter);
            }
            CSharp.IndexerBody body = CSharp.IndexerBody.NewFull(accessors);
            CSharp.IndexerDeclaration declaration = CSharp.IndexerDeclaration.New(null, null, declarator, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewIndexer(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateMethodClassMemberDeclarator(MethodClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.MethodModifiers modifiers = TranslateClassMemberAccessibilityAsMethodModifiers(n.Access);
            if (n.IsAsync)
                modifiers = modifiers.WithItems(Sequence.Append(modifiers.Items, CSharp.MethodModifier.NewAsync()));
            if (n.IsStatic)
                modifiers = modifiers.WithItems(Sequence.Append(modifiers.Items, CSharp.MethodModifier.NewStatic()));
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.MemberName memberName = CSharp.MemberName.NewSimple(name);
            CSharp.FormalParameterList parameters = TranslateAsFormalParameterList(n.Parameters);
            CSharp.ReturnType returnType;
            if (n.ResultType != null)
                returnType = CSharp.ReturnType.NewValued(TranslateTypeExpression(n.ResultType));
            else
                returnType = CSharp.ReturnType.NewVoid();
            CSharp.MethodBody body = CSharp.MethodBody.NewFull(TranslateClassMethodBodyAsMethodBlock(n.Body));
            CSharp.MethodHeader header = CSharp.MethodHeader.New(null, modifiers, false, returnType, memberName, null, parameters);
            CSharp.MethodDeclaration declaration = CSharp.MethodDeclaration.New(header, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewMethod(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateVirtualMethodClassMemberDeclarator(VirtualMethodClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.MethodModifiers modifiers = TranslateClassMemberAccessibilityAsMethodModifiers(n.Access);
            if (n.IsAsync)
                modifiers = modifiers.WithItems(Sequence.Append(modifiers.Items, CSharp.MethodModifier.NewAsync()));
            modifiers = modifiers.WithItems(Sequence.Concat(modifiers.Items, TranslateClassMemberVirtualModifierAsMethodModifiers(n.Modifier).Items));
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.MemberName memberName = CSharp.MemberName.NewSimple(name);
            CSharp.FormalParameterList parameters = TranslateAsFormalParameterList(n.Parameters);
            CSharp.ReturnType returnType;
            if (n.ResultType != null)
                returnType = CSharp.ReturnType.NewValued(TranslateTypeExpression(n.ResultType));
            else
                returnType = CSharp.ReturnType.NewVoid();
            CSharp.MethodBody body = CSharp.MethodBody.NewFull(TranslateClassMethodBodyAsMethodBlock(n.Body));
            CSharp.MethodHeader header = CSharp.MethodHeader.New(null, modifiers, false, returnType, memberName, null, parameters);
            CSharp.MethodDeclaration declaration = CSharp.MethodDeclaration.New(header, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewMethod(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateAbstractMethodClassMemberDeclarator(AbstractMethodClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.MethodModifiers modifiers = TranslateClassMemberAccessibilityAsMethodModifiers(n.Access);
            modifiers = modifiers.WithItems(Sequence.Append(modifiers.Items, CSharp.MethodModifier.NewAbstract()));
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.MemberName memberName = CSharp.MemberName.NewSimple(name);
            CSharp.FormalParameterList parameters = TranslateAsFormalParameterList(n.Parameters);
            CSharp.ReturnType returnType;
            if (n.ResultType != null)
                returnType = CSharp.ReturnType.NewValued(TranslateTypeExpression(n.ResultType));
            else
                returnType = CSharp.ReturnType.NewVoid();
            CSharp.MethodBody body = CSharp.MethodBody.NewPartial();
            CSharp.MethodHeader header = CSharp.MethodHeader.New(null, modifiers, false, returnType, memberName, null, parameters);
            CSharp.MethodDeclaration declaration = CSharp.MethodDeclaration.New(header, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewMethod(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateExplicitMethodImplClassMemberDeclarator(ExplicitMethodImplClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.MethodModifiers modifiers = null;
            if (n.IsAsync)
                modifiers = CSharp.MethodModifiers.New(Sequence.Create(CSharp.MethodModifier.NewAsync()));
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.InterfaceType targetType = CSharp.InterfaceType.New(CSharp.TypeName.New(TranslateTypeName(n.Target)));
            CSharp.MemberName memberName = CSharp.MemberName.NewExplicit(targetType, name);
            CSharp.FormalParameterList parameters = TranslateAsFormalParameterList(n.Parameters);
            CSharp.ReturnType returnType;
            if (n.ResultType != null)
                returnType = CSharp.ReturnType.NewValued(TranslateTypeExpression(n.ResultType));
            else
                returnType = CSharp.ReturnType.NewVoid();
            CSharp.MethodBody body = CSharp.MethodBody.NewFull(TranslateClassMethodBodyAsMethodBlock(n.Body));
            CSharp.MethodHeader header = CSharp.MethodHeader.New(null, modifiers, false, returnType, memberName, null, parameters);
            CSharp.MethodDeclaration declaration = CSharp.MethodDeclaration.New(header, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewMethod(declaration));
        }

        public virtual ClassDeclarator CurrentClass { get; set; }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateConstructorClassMemberDeclarator(ConstructorClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (CurrentClass == null)
            {
                RuntimeErrorException e = new RuntimeErrorException(SR.CurrentClassOrStructNotAvailableCanNotTranslateConstructor);
                e.AddLocation(n.Context);
                throw e;
            }
            CSharp.ConstructorModifiers modifiers = TranslateClassMemberAccessibilityAsConstructorModifiers(n.Access);
            CSharp.Identifier name = CSharp.Identifier.New(CurrentClass.Name.Name);
            CSharp.FormalParameterList parameters = TranslateAsFormalParameterList(n.Parameters);
            CSharp.ConstructorDeclarator declarator = CSharp.ConstructorDeclarator.New(name, parameters);
            CSharp.ConstructorBody body = CSharp.ConstructorBody.NewFull(TranslateClassMethodBodyAsConstructorBlock(n.Body));
            CSharp.ConstructorDeclaration declaration = CSharp.ConstructorDeclaration.New(null, modifiers, declarator, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewConstructor(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateConstructorWithThisClassMemberDeclarator(ConstructorWithThisClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (CurrentClass == null)
            {
                RuntimeErrorException e = new RuntimeErrorException(SR.CurrentClassOrStructNotAvailableCanNotTranslateConstructor);
                e.AddLocation(n.Context);
                throw e;
            }
            CSharp.ConstructorModifiers modifiers = TranslateClassMemberAccessibilityAsConstructorModifiers(n.Access);
            CSharp.Identifier name = CSharp.Identifier.New(CurrentClass.Name.Name);
            CSharp.FormalParameterList parameters = TranslateAsFormalParameterList(n.Parameters);
            CSharp.ArgumentList arguments = TranslateArgumentList(n.Arguments);
            CSharp.ConstructorInitializer initializer = CSharp.ConstructorInitializer.NewThis(arguments);
            CSharp.ConstructorDeclarator declarator = CSharp.ConstructorDeclarator.New(name, parameters, initializer);
            CSharp.ConstructorBody body = CSharp.ConstructorBody.NewFull(TranslateClassMethodBodyAsConstructorBlock(n.Body));
            CSharp.ConstructorDeclaration declaration = CSharp.ConstructorDeclaration.New(null, modifiers, declarator, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewConstructor(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateConstructorWithBaseClassMemberDeclarator(ConstructorWithBaseClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (CurrentClass == null)
            {
                RuntimeErrorException e = new RuntimeErrorException(SR.CurrentClassOrStructNotAvailableCanNotTranslateConstructor);
                e.AddLocation(n.Context);
                throw e;
            }
            CSharp.ConstructorModifiers modifiers = TranslateClassMemberAccessibilityAsConstructorModifiers(n.Access);
            CSharp.Identifier name = CSharp.Identifier.New(CurrentClass.Name.Name);
            CSharp.FormalParameterList parameters = TranslateAsFormalParameterList(n.Parameters);
            CSharp.ArgumentList arguments = TranslateArgumentList(n.Arguments);
            CSharp.ConstructorInitializer initializer = CSharp.ConstructorInitializer.NewBase(arguments);
            CSharp.ConstructorDeclarator declarator = CSharp.ConstructorDeclarator.New(name, parameters, initializer);
            CSharp.ConstructorBody body = CSharp.ConstructorBody.NewFull(TranslateClassMethodBodyAsConstructorBlock(n.Body));
            CSharp.ConstructorDeclaration declaration = CSharp.ConstructorDeclaration.New(null, modifiers, declarator, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewConstructor(declaration));
        }

        public virtual Sequence<CSharp.ClassMemberDeclaration> TranslateStaticConstructorClassMemberDeclarator(StaticConstructorClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            if (CurrentClass == null)
            {
                RuntimeErrorException e = new RuntimeErrorException(SR.CurrentClassOrStructNotAvailableCanNotTranslateStaticConstructor);
                e.AddLocation(n.Context);
                throw e;
            }
            CSharp.StaticConstructorModifiers modifiers = CSharp.StaticConstructorModifiers.NewStaticExtern(false);
            CSharp.Identifier name = CSharp.Identifier.New(CurrentClass.Name.Name);
            CSharp.StaticConstructorBody body = CSharp.StaticConstructorBody.NewFull(TranslateClassMethodBodyAsConstructorBlock(n.Body));
            CSharp.StaticConstructorDeclaration declaration = CSharp.StaticConstructorDeclaration.New(null, modifiers, name, body);
            return Sequence.Create(CSharp.ClassMemberDeclaration.NewStaticConstructor(declaration));
        }

        public virtual CSharp.TypeDeclaration TranslateTypeDeclarator(TypeDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return n.AcceptTypeDeclaratorTranslator(this);
        }

        public virtual CSharp.EnumDeclaration TranslateEnumDeclarator(EnumDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            Sequence<CSharp.EnumMemberDeclaration> members = Sequence.GetEmpty<CSharp.EnumMemberDeclaration>();
            if (n.IsReversed)
            {
                foreach (EnumItemDeclarator declarator in n.Items)
                    foreach (Identifier id in declarator.Names)
                        members = Sequence.Prepend(CSharp.EnumMemberDeclaration.New(null, CSharp.Identifier.New(id.Name)), members);
            }
            else
            {
                foreach (EnumItemDeclarator declarator in n.Items)
                    foreach (Identifier id in declarator.Names)
                        members = Sequence.Append(members, CSharp.EnumMemberDeclaration.New(null, CSharp.Identifier.New(id.Name)));
            }
            CSharp.EnumMemberDeclarations declarations = null;
            if (members.Count > 0)
                declarations = CSharp.EnumMemberDeclarations.New(members);
            CSharp.EnumBody body = CSharp.EnumBody.New(declarations);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.Attributes attributes = GetCommonTypeAttributes();
            CSharp.EnumModifiers modifiers = CSharp.EnumModifiers.New(Sequence.Create(
                n.IsInternal ? CSharp.EnumModifier.NewInternal() : CSharp.EnumModifier.NewPublic()
            ));
            CSharp.EnumDeclaration declaration = CSharp.EnumDeclaration.New(attributes, modifiers, name, null, body);
            return declaration;
        }

        public virtual CSharp.TypeDeclaration TranslateEnumTypeDeclarator(EnumTypeDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.EnumDeclaration declaration = TranslateEnumDeclarator(n.Declarator);
            return CSharp.TypeDeclaration.NewEnum(declaration);
        }

        public virtual CSharp.TypeDeclaration TranslateStructTypeDeclarator(StructTypeDeclarator n)
        {
            // TODO
            throw new NotImplementedException();
        }

        public virtual CSharp.TypeDeclaration TranslateUnionTypeDeclarator(UnionTypeDeclarator n)
        {
            // TODO
            throw new NotImplementedException();
        }

        public virtual CSharp.TypeDeclaration TranslateVisitorTypeDeclarator(VisitorTypeDeclarator n)
        {
            // TODO
            throw new NotImplementedException();
        }

        public virtual CSharp.InterfaceDeclaration TranslateInterfaceDeclarator(InterfaceDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            Sequence<CSharp.InterfaceMemberDeclaration> members = Sequence.GetEmpty<CSharp.InterfaceMemberDeclaration>();
            foreach (InterfaceMemberDeclarator declarator in n.Members)
                members = Sequence.Append(members, TranslateInterfaceMemberDeclarator(declarator));
            CSharp.InterfaceMemberDeclarations declarations = null;
            if (members.Count > 0)
                declarations = CSharp.InterfaceMemberDeclarations.New(members);
            CSharp.InterfaceBody body = CSharp.InterfaceBody.New(declarations);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.InterfaceModifiers modifiers = CSharp.InterfaceModifiers.New(Sequence.Create(
                n.IsInternal ? CSharp.InterfaceModifier.NewInternal() : CSharp.InterfaceModifier.NewPublic()
            ));
            CSharp.InterfaceDeclaration declaration = CSharp.InterfaceDeclaration.New(null, modifiers, true, name, null, null, null, body);
            return declaration;
        }

        public virtual CSharp.TypeDeclaration TranslateInterfaceTypeDeclarator(InterfaceTypeDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            CSharp.InterfaceDeclaration declaration = TranslateInterfaceDeclarator(n.Declarator);
            return CSharp.TypeDeclaration.NewInterface(declaration);
        }

        public virtual bool IsAllowedInStruct(ClassMemberDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            switch (n.Tag)
            {
                case ClassMemberDeclaratorCategory.VirtualEvent:
                    return n.AsVirtualEvent.Modifier == ClassMemberVirtualModifier.Override;
                case ClassMemberDeclaratorCategory.VirtualEventBlock:
                    return n.AsVirtualEventBlock.Modifier == ClassMemberVirtualModifier.Override;
                case ClassMemberDeclaratorCategory.AbstractEvent:
                    return false;
                case ClassMemberDeclaratorCategory.VirtualProperty:
                    return n.AsVirtualProperty.Modifier == ClassMemberVirtualModifier.Override;
                case ClassMemberDeclaratorCategory.VirtualPropertyField:
                    return n.AsVirtualPropertyField.Modifier == ClassMemberVirtualModifier.Override;
                case ClassMemberDeclaratorCategory.VirtualPropertyBlock:
                    return n.AsVirtualPropertyBlock.Modifier == ClassMemberVirtualModifier.Override;
                case ClassMemberDeclaratorCategory.AbstractProperty:
                    return false;
                case ClassMemberDeclaratorCategory.VirtualIndexer:
                    return n.AsVirtualIndexer.Modifier == ClassMemberVirtualModifier.Override;
                case ClassMemberDeclaratorCategory.VirtualIndexerBlock:
                    return n.AsVirtualIndexerBlock.Modifier == ClassMemberVirtualModifier.Override;
                case ClassMemberDeclaratorCategory.AbstractIndexer:
                    return false;
                case ClassMemberDeclaratorCategory.VirtualMethod:
                    return n.AsVirtualMethod.Modifier == ClassMemberVirtualModifier.Override;
                case ClassMemberDeclaratorCategory.AbstractMethod:
                    return false;
                default:
                    return true;
            }
        }

        public virtual Sequence<CSharp.StructMemberDeclaration> ConvertToStructMembers(Sequence<CSharp.ClassMemberDeclaration> n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return n.Map(x =>
            {
                switch (x.Tag)
                {
                    case CSharp.ClassMemberDeclarationCategory.Constant: return CSharp.StructMemberDeclaration.NewConstant(x.AsConstant.Declaration);
                    case CSharp.ClassMemberDeclarationCategory.Field: return CSharp.StructMemberDeclaration.NewField(x.AsField.Declaration);
                    case CSharp.ClassMemberDeclarationCategory.Method: return CSharp.StructMemberDeclaration.NewMethod(x.AsMethod.Declaration);
                    case CSharp.ClassMemberDeclarationCategory.Property: return CSharp.StructMemberDeclaration.NewProperty(x.AsProperty.Declaration);
                    case CSharp.ClassMemberDeclarationCategory.Event: return CSharp.StructMemberDeclaration.NewEvent(x.AsEvent.Declaration);
                    case CSharp.ClassMemberDeclarationCategory.Indexer: return CSharp.StructMemberDeclaration.NewIndexer(x.AsIndexer.Declaration);
                    case CSharp.ClassMemberDeclarationCategory.Operator: return CSharp.StructMemberDeclaration.NewOperator(x.AsOperator.Declaration);
                    case CSharp.ClassMemberDeclarationCategory.Constructor: return CSharp.StructMemberDeclaration.NewConstructor(x.AsConstructor.Declaration);
                    case CSharp.ClassMemberDeclarationCategory.Destructor:
                        RuntimeErrorException e = new RuntimeErrorException(SR.DestructorsNotAllowedInStructCanNotConvertDestructorMember);
                        e.AddLocation(x.Context);
                        throw e;
                    case CSharp.ClassMemberDeclarationCategory.StaticConstructor: return CSharp.StructMemberDeclaration.NewStaticConstructor(x.AsStaticConstructor.Declaration);
                    case CSharp.ClassMemberDeclarationCategory.Type: return CSharp.StructMemberDeclaration.NewType(x.AsType.Declaration);
                    default: throw new InvalidOperationException(SR.InvalidClassMemberDeclaration);
                }
            });
        }

        public virtual CSharp.TypeDeclaration TranslateClassDeclarator(ClassDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            ClassDeclarator saved = CurrentClass;
            CurrentClass = n;
            Sequence<CSharp.ClassMemberDeclaration> members = Sequence.GetEmpty<CSharp.ClassMemberDeclaration>();
            if (n.Modifier == ClassVirtualModifier.Struct)
            {
                foreach (ClassMemberDeclarator declarator in n.Members)
                {
                    if (!IsAllowedInStruct(declarator))
                    {
                        RuntimeErrorException e = new RuntimeErrorException(SR.VirtualOrAbstractMemberNotAllowedInStruct);
                        e.AddLocation(n.Context);
                        throw e;
                    }
                    members = Sequence.Concat(members, TranslateClassMemberDeclarator(declarator));
                }
            }
            else
            {
                foreach (ClassMemberDeclarator declarator in n.Members)
                    members = Sequence.Concat(members, TranslateClassMemberDeclarator(declarator));
            }
            CurrentClass = saved;
            CSharp.ClassMemberDeclarations declarations = null;
            if (members.Count > 0)
                declarations = CSharp.ClassMemberDeclarations.New(members);
            CSharp.ClassBody body = CSharp.ClassBody.New(declarations);
            CSharp.Identifier name = CSharp.Identifier.New(n.Name.Name);
            CSharp.Attributes attributes = GetCommonTypeAttributes();
            Sequence<CSharp.ClassModifier> modifierItems;
            if (n.IsInternal)
                modifierItems = Sequence.Create(CSharp.ClassModifier.NewInternal());
            else
                modifierItems = Sequence.Create(CSharp.ClassModifier.NewPublic());
            modifierItems = Sequence.Concat(modifierItems, TranslateClassVirtualModifierAsClassModifiers(n.Modifier));
            CSharp.ClassModifiers modifiers = CSharp.ClassModifiers.New(modifierItems);
            CSharp.ClassBase classBase = null;
            if (n.Bases.Count >= 2)
            {
                CSharp.ClassType classType = CSharp.ClassType.NewNamedClass(CSharp.TypeName.New(TranslateTypeName(n.Bases[0])));
                Sequence<CSharp.InterfaceType> interfaces = n.Bases.GetRange(1, n.Bases.Count - 1).Map(x => CSharp.InterfaceType.New(CSharp.TypeName.New(TranslateTypeName(x))));
                classBase = CSharp.ClassBase.NewClassTypeAndInterfaceTypeList(classType, CSharp.InterfaceTypeList.New(interfaces));
            }
            else if (n.Bases.Count == 1)
            {
                CSharp.ClassType classType = CSharp.ClassType.NewNamedClass(CSharp.TypeName.New(TranslateTypeName(n.Bases[0])));
                classBase = CSharp.ClassBase.NewClassTypeOnly(classType);
            }
            if (n.Modifier == ClassVirtualModifier.Struct)
            {
                CSharp.StructModifiers structModifiers = CSharp.StructModifiers.New(Sequence.Create(
                    n.IsInternal ? CSharp.StructModifier.NewInternal() : CSharp.StructModifier.NewPublic()
                ));
                CSharp.StructInterfaces structInterfaces = null;
                if (n.Bases.Count > 0)
                {
                    Sequence<CSharp.InterfaceType> interfaces = n.Bases.Map(x => CSharp.InterfaceType.New(CSharp.TypeName.New(TranslateTypeName(x))));
                    structInterfaces = CSharp.StructInterfaces.New(CSharp.InterfaceTypeList.New(interfaces));
                }
                Sequence<CSharp.StructMemberDeclaration> structMembers = ConvertToStructMembers(members);
                CSharp.StructMemberDeclarations structDeclarations = null;
                if (members.Count > 0)
                    structDeclarations = CSharp.StructMemberDeclarations.New(structMembers);
                CSharp.StructBody structBody = CSharp.StructBody.New(structDeclarations);
                CSharp.StructDeclaration declaration = CSharp.StructDeclaration.New(attributes, structModifiers, true, name, null, structInterfaces, null, structBody);
                return CSharp.TypeDeclaration.NewStruct(declaration);
            }
            else
            {
                CSharp.ClassDeclaration declaration = CSharp.ClassDeclaration.New(attributes, modifiers, true, name, null, classBase, null, body);
                return CSharp.TypeDeclaration.NewClass(declaration);
            }
        }

        public virtual CSharp.TypeDeclaration TranslateClassTypeDeclarator(ClassTypeDeclarator n)
        {
            if (n == null)
                throw new ArgumentNullException(nameof(n));
            return TranslateClassDeclarator(n.Declarator);
        }
        #endregion
    }
}
